cx_Freeze python 打包 APScheduler 定时任务异常问题解决
异常信息:
File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1105, in _create_plugin_instanceplugin_cls = class_container[alias]~~~~~~~~~~~~~~~^^^^^^^
KeyError: 'interval'During handling of the above exception, another exception occurred:Traceback (most recent call last):File "FlaskKspiceServer.py", line 496, in startServiceFile "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 486, in add_job"trigger": self._create_trigger(trigger, trigger_args),^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1132, in _create_triggerreturn self._create_plugin_instance("trigger", trigger, trigger_args)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1108, in _create_plugin_instanceplugin_cls = class_container[alias] = plugin_container[alias].load()^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\importlib\metadata\__init__.py", line 205, in loadmodule = import_module(match.group('module'))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_modulereturn _bootstrap._gcd_import(name[level:], package, level)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "<frozen importlib._bootstrap>", line 1387, in _gcd_importFile "<frozen importlib._bootstrap>", line 1360, in _find_and_loadFile "<frozen importlib._bootstrap>", line 1324, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'apscheduler.triggers.interval'Traceback (most recent call last):File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1105, in _create_plugin_instanceplugin_cls = class_container[alias]~~~~~~~~~~~~~~~^^^^^^^
KeyError: 'interval'During handling of the above exception, another exception occurred:Traceback (most recent call last):File "FlaskKspiceServer.py", line 496, in startServiceFile "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 486, in add_job"trigger": self._create_trigger(trigger, trigger_args),^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1132, in _create_triggerreturn self._create_plugin_instance("trigger", trigger, trigger_args)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 1108, in _create_plugin_instanceplugin_cls = class_container[alias] = plugin_container[alias].load()^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\importlib\metadata\__init__.py", line 205, in loadmodule = import_module(match.group('module'))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_modulereturn _bootstrap._gcd_import(name[level:], package, level)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "<frozen importlib._bootstrap>", line 1387, in _gcd_importFile "<frozen importlib._bootstrap>", line 1360, in _find_and_loadFile "<frozen importlib._bootstrap>", line 1324, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'apscheduler.triggers.interval'During handling of the above exception, another exception occurred:Traceback (most recent call last):File "D:\Programs\Python\Python312\Lib\site-packages\cx_Freeze\initscripts\__startup__.py", line 121, in runmodule_init.run(f"__main__{name}")File "D:\Programs\Python\Python312\Lib\site-packages\cx_Freeze\initscripts\console.py", line 25, in runexec(code, main_globals)File "FlaskKspiceServer.py", line 563, in <module>File "FlaskKspiceServer.py", line 519, in startServiceFile "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\background.py", line 40, in shutdownsuper().shutdown(*args, **kwargs)File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\blocking.py", line 22, in shutdownsuper().shutdown(wait)File "D:\Programs\Python\Python312\Lib\site-packages\apscheduler\schedulers\base.py", line 232, in shutdownraise SchedulerNotRunningError
apscheduler.schedulers.SchedulerNotRunningError: Scheduler is not running
原因分析
APScheduler 的触发器(trigger)是通过动态导入的,打包工具不会自动识别这些“隐式依赖”,所以需要手动指定。
解决方法
1. PyInstaller 解决方案
方法一:在代码中显式导入
在你的主程序(如 FlaskKspiceServer.py)开头加上:
python
# 显式导入所有用到的 triggerimport apscheduler.triggers.intervalimport apscheduler.triggers.cronimport apscheduler.triggers.date
这样 PyInstaller/cx_Freeze 就会自动把这些模块打包进去。
方法二:PyInstaller 的 hiddenimports
如果用 PyInstaller,可以加参数:
sh
pyinstaller --hidden-import=apscheduler.triggers.interval --hidden-import=apscheduler.triggers.cron --hidden-import=apscheduler.triggers.date your_script.py
2. cx_Freeze 解决方案
在 setup.py 的 build_exe_options 里加:
python
此种办法解决成功!此种办法解决成功!此种办法解决成功!
build_exe_options = {"packages": ["apscheduler.triggers.interval", "apscheduler.triggers.cron", "apscheduler.triggers.date"],# ... 其他配置 ...}
3. 确认 APScheduler 版本
- APScheduler 4.x/3.x 都有类似问题,解决方法一样。
- 建议用最新版 APScheduler。
4. 关于 SchedulerNotRunningError
这个报错是因为前面触发器加载失败,导致 scheduler 没有启动,后续 shutdown 时自然报错。只要解决了 trigger 的导入问题,这个报错也会消失。
总结
最简单的做法:在你的主程序开头加如下代码:
python
import apscheduler.triggers.intervalimport apscheduler.triggers.cronimport apscheduler.triggers.date
然后重新打包即可。