目前,我正在与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模块?
答案 0 :(得分:6)
好的,我设法找到了解决方法。
比方说我们的项目看起来像这样
_/cythonheroku
|-- requirements.txt
|-- Procfile
|__/app
|-- __init__.py
|-- app.pyx
步骤如下:
.pyx
文件 container
并安装一些Linux软件包。因此,基本上,您需要:删除您的Procfile
并使用以下命令安装清单插件:
heroku update beta
heroku plugins:install @heroku-cli/plugin-manifest
heroku manifest:create
在创建的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并不那么重要)。
将堆栈更改为容器并推送:
heroku stack:set container
git push heroku master
您将在终端中看到很多东西。没关系。 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
文件的名称可以不同,但是您知道了。
将这两个文件添加到您的项目中,提交并推送到heroku。
就是这样。您的应用将启动,并可以通过网络使用。