如何使用 freeze_support 从冻结的 sys.argv 调用中获取真正的参数列表?
How can I get the real argument list from a frozen sys.argv call using freeze_support?
我有一个独特的问题 - 我的解决方案,我希望使用 pyinstaller 打包,在启动时 JIT 一些基于 sys.argv 的东西。当您在 Windows 上使用 multiprocessing
和 freeze_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
设置为 --multiprocessing-fork...
时,它会给我原来的 sys.argv
,即 --hello=True
我从来没有广泛使用过冻结可执行文件,但我有几个想法...
查看 multiprocessing.spawn._main()
,在此处复制原始 sys.argv
:
preparation_data = reduction.pickle.load(from_parent)
prepare(preparation_data)
如果您覆盖 Process.__new__
,您应该能够在 _bootstrap
之前 运行 编码(最终在进程对象上调用 run
),但在 [=收到 15=]。
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__
和 __setstate__
.
来挂钩 unpickle 过程
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 以取消 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)
所有这些都在加载新进程的过程中大致同时发生,我不能说哪个是最健壮的...
我有一个独特的问题 - 我的解决方案,我希望使用 pyinstaller 打包,在启动时 JIT 一些基于 sys.argv 的东西。当您在 Windows 上使用 multiprocessing
和 freeze_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
设置为 --multiprocessing-fork...
sys.argv
,即 --hello=True
我从来没有广泛使用过冻结可执行文件,但我有几个想法...
查看 multiprocessing.spawn._main()
,在此处复制原始 sys.argv
:
preparation_data = reduction.pickle.load(from_parent)
prepare(preparation_data)
如果您覆盖 Process.__new__
,您应该能够在 _bootstrap
之前 运行 编码(最终在进程对象上调用 run
),但在 [=收到 15=]。
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__
和 __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 以取消 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)
所有这些都在加载新进程的过程中大致同时发生,我不能说哪个是最健壮的...