问题描述
使用`pyinstaller`打包`flask`项目可以使客户免去安装一整套`python`及下载各种包的繁琐。
我的项目中使用了`flask_apscheduler`周期性定时任务,在编辑环境下测试正常。但用`pyinstaller`打包发布后踩到了一系列的坑。
先上示例源码。此源码来自 https://github.com/viniciuschiele/flask-apscheduler/blob/master/examples/allowed_host.py
(下面的源码与github上的示例略有改动)
from flask import Flask
from flask_apscheduler import APScheduler
class Config(object):
JOBS = [
{
'id': 'job1',
'func': 'app:job1',
'args': None,
'trigger': 'interval',
'seconds': 10
}
]
SCHEDULER_ALLOWED_HOSTS = ['my_servers_name']
SCHEDULER_API_ENABLED = True
def job1(a, b):
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(now)
if __name__ == '__main__':
app = Flask(__name__)
app.config.from_object(Config())
scheduler = APScheduler()
# it is also possible to set the list of servers directly
# scheduler.allowed_hosts = ['my_servers_name']
scheduler.init_app(app)
scheduler.start()
app.run()
打包好后运行时遇到的错误:ModuleNotFoundError: No module named 'app'
Traceback (most recent call last):
File "apscheduler\util.py", line 303, in ref_to_obj
ModuleNotFoundError: No module named 'app'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "app.py", line 727, in <module>
scheduler.init_app(app)
File "flask_apscheduler\scheduler.py", line 82, in init_app
File "flask_apscheduler\scheduler.py", line 328, in _load_jobs
File "flask_apscheduler\scheduler.py", line 160, in add_job
File "apscheduler\schedulers\base.py", line 434, in add_job
File "apscheduler\job.py", line 49, in __init__
File "apscheduler\job.py", line 162, in _modify
File "apscheduler\util.py", line 305, in ref_to_obj
LookupError: Error resolving reference app:save_heartbeat: could not import module
[11764] Failed to execute script app
解决办法:使用注解方式定义任务
代码改为如下:
from flask import Flask
from flask_apscheduler import APScheduler
import datetime
class Config(object):
SCHEDULER_API_ENABLED = True
scheduler = APScheduler()
# interval examples
@scheduler.task('interval', id='do_job_1', seconds=5, misfire_grace_time=900)
def job1():
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(now)
if __name__ == '__main__':
app = Flask(__name__)
app.config.from_object(Config())
scheduler.init_app(app)
scheduler.start()
app.run()
再次使用`pyinstaller`打包后运行,问题完美解决。