使用 Pyinstaller 打包 APIFlask 报错 AttributeError module 'apiflask' has no attribute 'settings'

这个主题用来追踪和讨论上面的 bug。

问题找到了,是apiflask的app.py里面引入了setting文件,
第361行 self.config.from_object(‘apiflask.settings’),
这个文件在pyinstaller的时候并不会一起打包进去,
我使用pyinstaller -F --add-data=“venv\Lib\site-packages\apiflask\settings.py;venv\Lib\sitepackages\apiflask\settings.py” app.py
但是这样在pyinstaller的时候就会报错,

最后我是手动全部使用self.config[‘OPENAPI_VERSION’]='3.0.3’这样的方式,
替换了self.config.from_object(‘apiflask.settings’),
目前来看是可以查看http://127.0.0.1:5000/docs的,
但是我不知道会不会导致一些问题。

请问有没有什么好的办法呢

能不能麻烦提供一个最小示例?包括打包使用的命令以及 Pyinstaller 版本。我在本地试试看。

如果能把项目上传到 GitHub 那就更好了 :stuck_out_tongue:

我就是用的你最简单的那个示例:
以下是全部代码

from flask import Flask
from apiflask import APIFlask, Schema, abort
from apiflask.fields import Integer, String
from apiflask.validators import Length, OneOf

app = APIFlask(__name__)

pets = [
    {'id': 0, 'name': 'Kitty', 'category': 'cat'},
    {'id': 1, 'name': 'Coco', 'category': 'dog'},
    {'id': 2, 'name': 'Flash', 'category': 'cat'}
]


class PetIn(Schema):
    name = String(required=True, validate=Length(0, 10))
    category = String(required=True, validate=OneOf(['dog', 'cat']))


class PetOut(Schema):
    id = Integer()
    name = String()
    category = String()


@app.get('/')
def say_hello():
    return {'message': 'Hello!'}


@app.get('/pets/<int:pet_id>')
@app.output(PetOut)
def get_pet(pet_id):
    if pet_id > len(pets) - 1 or pets[pet_id].get('deleted'):
        abort(404)
    return pets[pet_id]


@app.get('/pets')
@app.output(PetOut(many=True))
def get_pets():
    return pets

if __name__ == '__main__':
    app.run()

下面是requirements

altgraph==0.17.3
APIFlask==1.2.3
apispec==6.0.2
cachetools==5.3.0
click==8.1.3
colorama==0.4.6
Flask==2.2.3
Flask-HTTPAuth==4.7.0
flask-marshmallow==0.14.0
importlib-metadata==6.0.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.2
marshmallow==3.19.0
packaging==23.0
pefile==2023.2.7
py2exe==0.13.0.0
pyinstaller==5.8.0
pyinstaller-hooks-contrib==2023.0
pywin32-ctypes==0.2.0
six==1.16.0
webargs==8.2.0
Werkzeug==2.2.3
zipp==3.15.0

打包的命令是

pyinstaller -F app.py

pyinstaller打包的时候不会打包我们的配置文件,需要使用 --add-data='app\config;app\config’等命令,但是apiflask等这种安装的模块,我如果使用 --add-data=‘venv\Lib\site-packages\apiflask’,因为在虚拟环境里,可能会无法打包配置文件,主要我python才刚刚入门,不是很懂这些,所以只能修改了apiflask里面的app.py文件361行,将selft.config.from_object全部写成了self.confg[“xxx”]=xxx这样的,这样就跳过了打包配置文件,但是不知道会不会导致问题。

看起来是 Pyinstaller 的 bug。

你那样做没问题。下周我再具体研究下怎么回事。

BTW,代码记得用正确的格式插入。

image

使用下面的命令声明隐式导入的模块即可:

python -m PyInstaller -F ./main.py --hidden-import=apiflask.settings

具体参考 @tkzt 在这里的回复: