You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pyinstaller打包后pool.apply_async不执行目标函数反而调用主函数求助

故障原因

Windows 平台下 Python multiprocessing 模块创建子进程默认使用 spawn 模式,子进程启动时会重新导入完整的主模块代码。使用 PyInstaller 等工具打包为 exe 后,子进程无法正常触发 __name__ == '__main__' 的保护逻辑,每次创建子进程都会重新执行主函数代码,叠加你配置的单实例文件锁限制,子进程启动后会直接报错退出,因此目标函数uninstall_software_sub不会被执行。

解决方案

步骤1:添加多进程打包兼容代码

在__name__ == '__main__'代码块的最开头调用multiprocessing.freeze_support(),该函数专门用于适配打包场景的多进程兼容,不会影响源码直接运行的效果。
修改后的主入口代码示例:

import multiprocessing
# 其余原有导入保持不变

if __name__ == '__main__':
    # 新增该行,必须放在主入口所有代码最前面
    multiprocessing.freeze_support()
    print("main function called")
    try:
        # 使用文件锁,限制单进程
        parent_folder = "C:\\Program Files (x86)\\ctyun\\eCloudDeskDRT\\sdk"
        if not os.path.exists(parent_folder):
            os.makedirs(parent_folder)
        lock_file_name = 'eCloudDeskDRTSrv.lock'
        lock_file_path = os.path.join(parent_folder, lock_file_name)
        lock_file_fd = open(lock_file_path, 'w')
        portalocker.lock(lock_file_fd, portalocker.LOCK_EX | portalocker.LOCK_NB)
        lock_file_fd.writelines(str(os.getpid()))
        lock_file_fd.flush()
    except BaseException as e:
        print("CloudDeskDRTSrv.exe have another instance running.")
        sys.exit()

步骤2:补全进程池生命周期管理

你当前调用apply_async提交任务后没有等待子进程执行完成,如果主进程提前退出,子进程会被系统直接杀死,需要补充进程池的关闭和等待逻辑:

def uninstall_software(software_name, uninstall_callback):
    log_utils.get_logger().info("uninstall_software software_name=%s", software_name)
    uninstall_info = get_uninstall_software_info(software_name)
    uninstall_string = uninstall_info.uninstall_string
    uninstall_process_name = uninstall_process.get(software_name, None)
    log_utils.get_logger().info(os.getpid())
    pool = Pool(1)
    log_utils.get_logger().info('apply_async')
    pool.apply_async(func=third_party_software_check.uninstall_software_sub,
                     args=(software_name, uninstall_string, uninstall_process_name),
                     callback=uninstall_callback)
    # 新增两行,关闭进程池并等待任务执行完成
    pool.close()
    pool.join()

如果你的程序是常驻后台服务,不需要同步等待卸载任务完成,也可以不加pool.join(),但需要确保主进程在卸载任务执行完成前不会退出。


内容的提问来源于stack exchange,提问作者Rongjie Shao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 12:42:03