uvicorn 和 fastAPI 与 pyinstaller 问题,当 uvicorn 工作人员 > 1 时

问题描述 投票:0回答:3

我查过 PyInstaller 和 FastAPI(超出最大递归深度)Pyinstaller编译的Uvicorn服务器无法正确启动

FastAPI 演示

main.py
:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"hello": "world"}

if __name__ == '__main__':
    uvicorn.run(app, host="0.0.0.0", port=58000, reload=False)

首先运行 pyinstaller

pyinstaller -F main.py --clean
并在规范中添加
hidden_imports

hidden_imports=[
                'uvicorn.logging',
                'uvicorn.loops',
                'uvicorn.loops.auto',
                'uvicorn.protocols',
                'uvicorn.protocols.http',
                'uvicorn.protocols.http.auto',
                'uvicorn.protocols.websockets',
                'uvicorn.protocols.websockets.auto',
                'uvicorn.lifespan',
                'uvicorn.lifespan.on',
            ]

效果很好,但是当workers大于1时应用程序必须是字符串:

WARNING:  You must pass the application as an import string to enable 'reload' or 'workers'.

所以我改为:

if __name__ == '__main__':
    uvicorn.run("main:app", host="0.0.0.0", port=58000, reload=False, workers=2)

完成此操作后,我运行了应用程序

dist/main
,它创建了许多如下所示的应用程序,快速使用 100% CPU 和 100% 内存:

error message

适用于 Python 3.8.3 和 pyinstaller 4.0

python pyinstaller fastapi uvicorn
3个回答
5
投票

一开始就调用(在Windows上)

mutiprocessing.freeze_support()
很重要,请参阅官方文档

import multiprocessing
...
...
...
if __name__ == '__main__':
    mutiprocessing.freeze_support()
    uvicorn.run("main:app", host="0.0.0.0", port=58000, reload=False, workers=2)

此外,可能需要将模块

main
添加为隐藏导入。


2
投票

对我来说这看起来像是无限递归。我怀疑原因与

main:app
处的自引用和一些 PyInstaller
sys
黑魔法将
__name__
设置为
__main__
有关。

我建议将

app
移至单独的模块中,并在
uvicorn.run()
中从该模块引用它:

# app.py
from fastapi import FastAPI


app = FastAPI()

@app.get("/")
def root():
    return {"hello": "world"}
# main.py
import uvicorn


if __name__ == "__main__":
    uvicorn.run("app:app", host="0.0.0.0", port=58000, reload=False, workers=2)

另外,不要忘记添加

app.py
作为 PyInstaller 的隐藏导入:

hidden_imports=[
    'uvicorn.logging',
    'uvicorn.loops',
    'uvicorn.loops.auto',
    'uvicorn.protocols',
    'uvicorn.protocols.http',
    'uvicorn.protocols.http.auto',
    'uvicorn.protocols.websockets',
    'uvicorn.protocols.websockets.auto',
    'uvicorn.lifespan',
    'uvicorn.lifespan.on',
    'app',
]

0
投票

在 Attila Viniczai 发布的上述第二个解决方案中, 请额外添加一行,这样它将停止无限递归问题。

# main.py
import uvicorn
import multiprocessing


if __name__ == "__main__":
    multiprocessing.freeze_support()
    uvicorn.run("app:app", host="0.0.0.0", port=58000, reload=False, workers=2)
© www.soinside.com 2019 - 2024. All rights reserved.