1

我有一个独特的问题 - 我的解决方案,我希望使用 pyinstaller 打包,在启动时基于 sys.argv JITs 一些东西。在 Windows 上使用multiprocessingwithfreeze_support时,多处理需要传入不同的参数来初始化新进程。当调用目标函数时,最终会设置原始的 sys.argv。如何在调用目标函数之前获取原始 sys.argv?

import sys
import multiprocessing
print('ArgV:', sys.argv)


def print_argv():
    print(sys.argv)

if __name__ == '__main__':
    multiprocessing.freeze_support()
    print_argv()
    p = multiprocessing.Process(target=print_argv)
    p.start()
    p.join()

当使用 pyinstaller 打包并使用 运行时--hello=True,会产生:

ArgV: ['scratch.exe', '--hello=True']
['scratch.exe', '--hello=True']
ArgV: ['scratch.exe', '--multiprocessing-fork', 'parent_pid=16096', 'pipe_handle=380']
['scratch.exe', '--hello=True']

我想要一些魔术代码,它可以给我我原来sys.argv的 ,也就是说--hello=True,什么时候sys.argv设置为--multiprocessing-fork...

4

1 回答 1

1

我从来没有广泛使用过冻结可执行文件,但我有几个想法......

看一下multiprocessing.spawn._main(),复制原件sys.argv发生在这里:

preparation_data = reduction.pickle.load(from_parent)
prepare(preparation_data)

如果您覆盖Process.__new__,您应该能够在之前运行代码_bootstrap(最终调用run进程对象),但在sys.argv接收到之后。

import sys
import multiprocessing
print('ArgV:', sys.argv)

def print_argv():
    print(sys.argv)
    
class myProcess(multiprocessing.Process):
    def __new__(cls, *args, **kwargs):
        if __name__ == "__mp_main__":
            print("hook", sys.argv)
        instance = super(myProcess, cls).__new__(cls) 
        instance.__init__(*args, **kwargs)
        return instance

if __name__ == '__main__':
    multiprocessing.freeze_support()
    print_argv()
    p = myProcess(target=print_argv)
    p.start()
    p.join()

__getstate__另一个想法是通过覆盖和来挂钩 unpickle 过程__setstate__

class myProcess(multiprocessing.Process):
    
    def __getstate__(self):
        return self.__dict__.copy()
    
    def __setstate__(self, state):
        print("hook", sys.argv)
        self.__dict__.update(state)

最后,您可以挂钩当 pickle 查找要取消腌制的自定义类时生成的审计事件:

class myProcess(multiprocessing.Process):
    pass

def hook(event_name, args):
    if "pickle.find_class" in event_name:
        if args[1] == myProcess.__name__:
            print("hook", sys.argv)
        
sys.addaudithook(hook)

所有这些都在加载新进程期间大致同时发生,我不能说哪个是最强大的......

于 2021-06-28T22:23:50.637 回答