首页 > 解决方案 > pool.apply_async 不调用目标函数,pyinstaller 打包后调用主函数

问题描述

我使用 Pool.async 执行卸载软件功能。如果不打包为 exe,它运行良好。但是当我将它打包为exe时,它不是调用目标函数而是调用主函数。这是我的代码。

if __name__ == '__main__':
    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()

def uninstall_software_sub(software_name, uninstall_string, uninstall_process_name):
    try:
        log_utils.get_logger().info('uninstall_software_sub')
        startupinfo = sp.STARTUPINFO()
        startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
        popen = sp.Popen(uninstall_string, stdout=sp.PIPE, stdin=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo)
        log_utils.get_logger().info(popen.pid)
        b_cmd = uninstall_string.encode("UTF-8")
        log_utils.get_logger().info("execute command %s", uninstall_string)

        b_outs, errs = popen.communicate(b_cmd, timeout=None)
        if uninstall_process_name:
            while windows_utils.check_process_running(uninstall_process_name):
                time.sleep(3)
        else:
            popen.wait()
        log_utils.get_logger().info("wait finished")
        outs = b_outs.decode('gbk', 'ignore')
        if errs:
            log_utils.get_logger().error(errs)
        else:
            log_utils.get_logger().info(outs)
    except UnicodeDecodeError as error:
        log_utils.get_logger().exception(error)
        outs = ""
    finally:
        if not popen.poll():
            popen.kill()
        uninstall_software_info = get_uninstall_software_info(software_name)
        uninstall_success = uninstall_software_info is None
        return uninstall_success


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
    if software_name in uninstall_process.keys():
        uninstall_process_name = uninstall_process.get(software_name)
    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)

unisntall_software_sub 不执行,但执行 pool.apply_async 时会调用 main 函数。这是日志输出。有人可以帮助我吗? 在此处输入图像描述

标签: pyinstallerpython-multiprocessing

解决方案


我发现 pyinstaller 支持多处理。但是需要在源代码中添加一些命令。我在主函数下方添加了 multiprocessing.freeze_support() 。它工作得很好。这是源代码:

if __name__ == '__main__':
    print("main function called")
    multiprocessing.freeze_support()
    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()

推荐阅读