pyinstaller打包之后的windows程序无法正常运行多进程(multiprocessing与argparse)

本文介绍了在Windows环境下,使用PyInstaller打包后的程序遇到的两个问题及其解决方法。一是全局变量在多进程(multiprocessing)中无法共享,解决方案是通过参数传递变量值;二是使用argparse命令行工具和multiprocessing时,出现unrecognized arguments错误,解决办法是修改命令行参数解析方式并添加`multiprocessing.freeze_support()`。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pyinstaller打包之后的windows程序无法正常运行多进程(multiprocessing与argparse)

一、windows环境下无法共享全局变量的值

同样的代码分别在linux环境以及windows环境有很大区别

代码片段:

# new_list,list_success_table是全局变量
print('task id:',task_id,'list_success_table:',list_success_table,'new_list:',new_list)

Linux环境正常输出全局变量list_success_table,new_list:
在这里插入图片描述

Windows环境运行无法获取到全局变量:

在这里插入图片描述

解决方法:

使用传参的方式传递变量值,例如:

process = multiprocessing.Process(target=mig_table_task_total, args=(p_id,new_list[0][p_id]))


原先只有p_id这一个输入参数,现增加new_list[0][p_id]),本例为list类型为输入参数

二、使用argparse命令行工具以及multiprocessing运行可执行文件报错

报错如下:

参数error: unrecognized arguments: --multiprocessing-fork parent_pid=37636 pipe_handle=1128

原因:
windows环境打包之后的可执行文件,在运行的时候会隐式生成命令行选项--multiprocessing-fork,会在运行多进程方法报错,然而在Linux环境运行一点问题没有。

解决方法:

需要改2个地方

1、 命令行参数方面修改

原参数是这么写的


parser.add_argument('--quite_mode', '-q', help='quite mode mig', action='store_true',
                    default='false')
parser.add_argument('-v', '--version', action='version', version=version + release_date, help='Display version')
args = parser.parse_args()


改为如下:
parser.add_argument('--quite_mode', '-q', help='quite mode mig', action='store_true',
                    default='false')
parser.add_argument('-v', '--version', action='version', version=version + release_date, help='Display version')

args, unparsed = parser.parse_known_args() 
# parse_known_args.只解析正确的参数列表,无效参数会被忽略且不报错,args是解析正确参数,unparsed是不被解析的错误参数,win多进程需要此写法

2、另外需要在main函数下方使用freeze_support()
if __name__ == '__main__':
    multiprocessing.freeze_support()

不然会一直从头循环运行本程序
### 使用 PyInstaller 打包多线程和多进程Python 应用程序 打包一个多线程或多进程的应用程序时,PyInstaller 需要特别处理这些特性以确保应用程序能够正常运行。以下是详细的说明: #### 处理多线程应用 对于多线程的应用,在大多数情况下,PyInstaller 可以很好地支持这类应用而不需要额外配置。然而,为了确保所有依赖项都被正确包含,建议使用 `--onefile` 或者 `--onedir` 参数来指定输出文件的形式。 ```bash pyinstaller --onefile your_multithreaded_script.py ``` 如果遇到任何缺失模块的问题,可以尝试通过隐藏导入的方式显式声明所需的模块[^2]。 #### 多进程应用的支持 当涉及到多进程编程时,情况会稍微复杂一些。Python 的 `multiprocessing` 模块在不同平台上表现有所不同,因此需要注意以下几点: - **Windows 平台**:默认情况下,子进程中不会自动加载主脚本所在的目录到系统的路径中。可以通过设置环境变量或修改启动方式解决这个问题。 - **Unix/Linux 和 macOS 平台**:通常只需要确保所有的资源都已正确嵌入即可工作良好。 为了让 PyInstaller 正确识别并打包 `multiprocessing` 相关的内容,可以在命令行参数中加入 `-p` 来指明附加的搜索路径,或者编辑 `.spec` 文件中的 `Analysis` 对象增加相应的隐含导入列表。 ```python from PyInstaller.utils.hooks import collect_submodules, copy_metadata hiddenimports = list(collect_submodules('your_package')) datas = [] a = Analysis(['your_multiprocessing_script.py'], pathex=['.'], hiddenimports=hiddenimports, datas=datas) pyz = PYZ(a.pure) exe = EXE(pyz,...) # 完整 spec 文件内容省略 ``` 此外,还需要注意的是某些特定版本的 PyInstaller 存在一个 bug 导致无法正确解析 `spawn` 启动方法下的 `__main__.pyc` 文件。针对此问题的一个解决方案是在构建前删除该 pyc 文件。 #### 示例代码片段 下面是一个简单的例子展示了如何创建一个既有多线程又涉及跨平台多进程的任务调度器,并成功利用 PyInstaller 进行打包。 ```python import threading import multiprocessing as mp import time def thread_task(name): """模拟耗时操作""" print(f'Thread {name} starting...') time.sleep(2) print(f'Thread {name} finished.') def process_task(): """执行另一个独立进程内的任务""" print("Process task started.") threads = [ threading.Thread(target=thread_task, args=(f't-{i}',)) for i in range(3)] for t in threads: t.start() for t in threads: t.join() if __name__ == '__main__': pool = mp.Pool(processes=2) results = [pool.apply_async(process_task) for _ in range(2)] for r in results: r.get() # 获取结果 print("All processes completed!") ``` 上述代码定义了一个混合使用了多线程和多进程结构的小型应用程序。按照前面提到的方法对其进行打包应该能顺利得到可执行文件。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值