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

时间:2018-08-02 13:33:27

标签: python heroku flask cython

目前,我正在与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: 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模块?

1 个答案:

答案 0 :(得分:6)

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

比方说我们的项目看起来像这样

_/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命令有点棘手-据我了解,您无法通过以下方式在heroku中正确运行cython应用程序:

    from app.app import app
    app.run()
    

    Heroku会输入一个错误消息,该地址已经被使用(由于某种原因,它将在本地运行您的应用程序,然后尝试启动您的Web应用程序,您会收到一个错误消息。我不知道,会尝试以某种方式解决此问题,但是atm并不那么重要)。

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

    heroku stack:set container
    git push heroku master
    
  6. 您将在终端中看到很多东西。没关系。 Heroku会尝试使用heroku.yml中指定的命令来运行您的应用程序,并且会出现错误。那是因为我们还没有cython文件。现在的问题是,编译后的文件对于每个操作系统,而且我猜每个机器都是唯一的(取决于我认为的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>
    

    然后,您可以使用命令行中生成的链接下载它。 注意:您必须复制2个文件-<file>.c<file>.cpython-36m-x86_64-linux-gnu.so.so文件的名称可以不同,但​​是您知道了。

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

  8. 就是这样。您的应用将启动,并可以通过网络使用。

http://cython.herokuapp.com/