如何在 heroku 上托管 cython web 应用程序?

How to host cython web app on heroku?

目前我正在玩 Cython 并试图弄清楚如何在 heroku 上托管 Cython Flask 应用程序(例如)。

假设我的项目看起来像这样(在 cython 编译之后):

_/cythonheroku
 |-- requirements.txt
 |-- run.py
 |-- Procfile
 |__/app
    |-- __init__.py
    |-- app.c
    |-- app.cpython-36m-darwin.so
    |-- app.pyx

现在,app.pyx 有一个标准的 Flask 应用程序,其中包含一些 cython 调整,如下所示:

#cython: infer_types=True
from flask import Flask

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    cdef long x = 10000000
    cdef long long y = 0
    cdef int i
    for i in range(x):
        y += i
    return str(y)

然后,使用命令 cythonize -i app/app.pyx 我编译我的 app.pyx 代码。

run.py 文件中我有:

from app.app import app

app.run()

从我的命令行 python run.py 开始,当我看到 for 循环的返回值时,将在本地主机上启动服务器。

问题: 将其推送到 heroku 后,我在 run.py:

的第一行收到错误
no module named app

据我所知——heroku 只是看不到我编译的应用程序文件。

UPD:Procfile 中的命令:

web: gunicorn run:app --log-file=-

UPD2: 经过一些测试后,我发现 Heroku 无法将 app.cpython-36m-darwin.so 识别为模块。这就是我收到该错误的原因。

现在的问题是——如何让 heroku 将 .so 文件识别为 python 模块?

好的,我设法找到了解决方案。

假设我们的项目是这样的

_/cythonheroku
 |-- requirements.txt
 |-- Procfile
 |__/app
    |-- __init__.py
    |-- app.pyx

步骤如下:

  1. 创建一个项目并将其推送到 heroku 而无需使用 cython 编译 .pyx 文件
  2. 您需要将堆栈设置为 container 并安装一些 linux 软件包。所以,基本上,你需要:
  3. 删除您的 Procfile 并安装清单插件:

    heroku update beta
    heroku plugins:install @heroku-cli/plugin-manifest
    heroku manifest:create
    
  4. 在创建的 heroku.yml 中,您需要指定包和 运行 命令。最小可行清单文件如下所示:

    setup:
      config: {}
    build:
      languages:
        - python
      packages:
        - build-essential
    run:
      web: 'gunicorn app.app:app'
    

    我们想安装 build-essential 以便 heroku 端的 linux 机器能够编译我们的 cython 代码。 run 命令有点棘手——据我所知,你不能 运行 你的 cython 应用程序在 heroku 中正确地使用像这样的东西:

    from app.app import app
    app.run()
    

    Heroku 会报错,该地址已被使用(出于某种原因,它会在本地 运行 你的应用程序,然后尝试启动你的网络应用程序,你会得到一个错误。我不我知道,我会尝试以某种方式解决这个问题,但 atm 它并不是那么关键)。

  5. 将你的堆栈更改为容器并推送:

    heroku stack:set container
    git push heroku master
    
  6. 你会在终端看到很多东西。没关系。 Heroku 将尝试使用 heroku.yml 中指定的命令 运行 你的应用程序,你会得到一个错误。那是因为我们还没有我们的 cython 文件。现在,问题是编译后的文件对于每个 OS 都是唯一的,而且我猜,每台机器(我认为取决于 CPU 芯片组)。 这就是为什么我们要在 heroku 端而不是本地 编译我们的文件。为此,您需要连接到 heroku 终端,只需键入:

    heroku run bash
    

    然后你需要简单地编译你的代码:

    cythonize -i app/app.pyx
    

    现在,每个 heroku dyno 都有自己的临时文件系统,带有最近部署代码的全新副本,因此您的编译文件根本不会保存。你需要在你的机器上下载它,添加到项目并再次推送到 heroku。你可以像这样用 transfer.sh 来做:

    curl --upload-file ./app/<your-file> https://transfer.sh/<name-of-file>
    

    然后用命令行生成的link就可以下载了。 注意: 您必须复制 2 个文件 — <file>.c<file>.cpython-36m-x86_64-linux-gnu.so.so 文件可以以不同的方式命名,但您明白了。

  7. 将这两个文件添加到您的项目中,提交并推送到 heroku。

  8. 就是这样。您的应用程序将启动并在网络上可用。

http://cython.herokuapp.com/