如何在 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
步骤如下:
- 创建一个项目并将其推送到 heroku 而无需使用 cython 编译
.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
命令有点棘手——据我所知,你不能 运行 你的 cython 应用程序在 heroku 中正确地使用像这样的东西:
from app.app import app
app.run()
Heroku 会报错,该地址已被使用(出于某种原因,它会在本地 运行 你的应用程序,然后尝试启动你的网络应用程序,你会得到一个错误。我不我知道,我会尝试以某种方式解决这个问题,但 atm 它并不是那么关键)。
将你的堆栈更改为容器并推送:
heroku stack:set container
git push heroku master
你会在终端看到很多东西。没关系。 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
文件可以以不同的方式命名,但您明白了。
将这两个文件添加到您的项目中,提交并推送到 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
步骤如下:
- 创建一个项目并将其推送到 heroku 而无需使用 cython 编译
.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
命令有点棘手——据我所知,你不能 运行 你的 cython 应用程序在 heroku 中正确地使用像这样的东西:from app.app import app app.run()
Heroku 会报错,该地址已被使用(出于某种原因,它会在本地 运行 你的应用程序,然后尝试启动你的网络应用程序,你会得到一个错误。我不我知道,我会尝试以某种方式解决这个问题,但 atm 它并不是那么关键)。
将你的堆栈更改为容器并推送:
heroku stack:set container git push heroku master
你会在终端看到很多东西。没关系。 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
文件可以以不同的方式命名,但您明白了。将这两个文件添加到您的项目中,提交并推送到 heroku。
就是这样。您的应用程序将启动并在网络上可用。