我在windows下用pyinstaller打包程序, 运行python3.11.6和python3.12.0都遇到同样的问题
前提说明
- 代码在macOS上运行正常,无论打包与否, 无论是否arm64
- windows上直接python运行没问题
- 下面的错误是pyinstaller打包后运行出现的错误
Traceback (most recent call last):
File "main.py", line 8, in <module>
File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module
File "process\scheduler.py", line 14, in <module>
File "multiprocess\context.py", line 150, in freeze_support
File "multiprocess\spawn.py", line 77, in freeze_support
File "multiprocess\spawn.py", line 120, in spawn_main
File "multiprocess\spawn.py", line 130, in _main
File "dill_dill.py", line 287, in load
File "dill_dill.py", line 442, in load
File "dill_dill.py", line 432, in find_class
AttributeError: Can't get attribute 'run_one' on <module 'process.scheduler' from 'C:\Users\xxx\AppData\Local\Temp\_MEI114562\process\scheduler.pyc'>
[3608] Failed to execute script 'main' due to unhandled exception!
如果你遇到这个问题,建议如下
- 不要怀疑python版本问题
- 不要怀疑pyinstaller的打包能力
- 如果pyinstaller打包时出现个别警告, 千万不要怀疑系统有问题
不要问我是怎么知道的。
问题根因:
multiprocess.freeze_support() 会在主进程中调用,以确保只有主进程执行其中的代码。这样就避免了在子进程中重新执行整个脚本。
问题总结
学艺不精,技术不行。
错误代码展示
if IS_WINDOWS:
multiprocess.freeze_support()
def run_one(tasks, name:string, *args, **kwargs):
try:
for key, task in tasks.items():
if key.lower() == name.lower():
logger.debug(f'[{task.__class__.__name__}] start...')
task.run()
logger.debug(f'[{task.__class__.__name__}] exit!')
return
logger.debug(f'[{name}] processor no exist, exit')
except KeyboardInterrupt:
logger.info('[main] process received keyboard interrupt signal')
正确代码
def run_one(tasks, name:string, *args, **kwargs):
try:
for key, task in tasks.items():
if key.lower() == name.lower():
logger.debug(f'[{task.__class__.__name__}] start...')
task.run()
logger.debug(f'[{task.__class__.__name__}] exit!')
return
logger.debug(f'[{name}] processor no exist, exit')
except KeyboardInterrupt:
logger.info('[main] process received keyboard interrupt signal')
if IS_WINDOWS:
multiprocess.freeze_support()