问题:
程序打包后,打开exe,软件重复启动直至电脑卡死关机。
原因:
这是一个关于Python中multiprocessing模块的问题。当在Windows系统上使用多进程时,在创建子进程时,会重新导入主模块,这可能导致无限递归创建子进程。为了避免这种情况,我们需要使用freeze_support()函数。
具体来说,当我们使用multiprocessing模块创建子进程时,子进程会导入主模块。如果主模块中没有保护措施,就会再次执行创建子进程的代码,从而导致无限循环。在Windows系统中,这个问题尤其突出,因为Windows没有fork系统调用,所以创建子进程时会重新导入主模块。
解决办法:
在主模块的入口点(即if name == 'main':块中)调用freeze_support()函数。这样可以确保当主模块被导入时,不会执行创建子进程的代码。
关于multiprocessing.freeze_support()
multiprocessing.freeze_support() 是 Python 中 multiprocessing 模块的一个重要函数,主要用于支持将 Python 程序打包成独立的可执行文件。以下是它的主要作用:
-
主要作用
支持程序打包(如 PyInstaller、py2exe)
当使用 PyInstaller、py2exe、cx_Freeze 等工具将 Python 程序打包成独立的可执行文件时
在多进程环境下,子进程需要重新导入主模块
freeze_support() 确保在多进程环境中正确初始化
-
防止 Windows 上的运行时错误
在 Windows 系统中,使用 multiprocessing 模块时
如果不调用 freeze_support(),可能会出现 RuntimeError
Windows 没有 fork 系统调用,所以需要特殊的处理来启动子进程
-
使用场景
基本用法
bash
import multiprocessing
def worker():
print("Worker process")
if __name__ == '__main__':
# 必须在使用 multiprocessing 之前调用
multiprocessing.freeze_support()
# 创建和启动进程
p = multiprocessing.Process(target=worker)
p.start()
p.join()
在打包的应用中
bash
import multiprocessing
import sys
def main():
# 主程序逻辑
print("Main process")
if __name__ == '__main__':
# 检查是否被冻结(打包成exe)
if getattr(sys, 'frozen', False):
multiprocessing.freeze_support()
main()
注意事项
- 位置重要
bash
# 正确:在 if __name__ == '__main__': 块中调用
if __name__ == '__main__':
multiprocessing.freeze_support()
# 其他代码
# 错误:不要在模块级别调用
# multiprocessing.freeze_support() # 不要这样写!
-
平台特定
主要针对 Windows 系统
在 Linux/macOS 上通常不需要,但有它也不会出错
建议总是包含以保持跨平台兼容性
-
与打包工具配合
bash
# PyInstaller 等工具会自动处理
# 但显式调用 freeze_support() 是良好的实践
如果不使用的后果
当程序被打包成 exe 且不使用 freeze_support() 时:
- Windows 上可能会抛出 RuntimeError
- 子进程可能无法正确启动
- 程序可能崩溃或行为异常