Python 多处理和 sys.argv
Python multiprocessing and sys.argv
sys.argv
值是否传递到多处理的分支?将 argv 传递给多进程的所有分支的正确方法是什么?
假设我有两个文件:test1.py:
import sys
if len(sys.argv) > 1:
env = sys.argv[1]
else:
env = 'test'
和main_code.py:
from test1 import *
import concurrent.futures
def f():
if env == 'test':
print('bu')
else:
print('not bu')
if __name__ == '__main__':
with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor:
for i in range(2):
executor.submit(f)
我从 cmd main.code.py 调用:python main_code.py zzz
。 sys.argv[1] 变量(即 'zzz')是否在每次调用 executor.submit(f)
时传递,因为它最初是从 text1.py 的导入中获得的?我的困惑来自于 concurrent.futures 基本上通过重新导入所有文件来创建单独的代码线程实例。
在 Windows 上,spawn 上下文是创建工作进程的唯一方法。
sys.argv
被复制到工作进程一次。
并非所有文件都重新导入。 unpickle 导入任务函数和参数只需要模块。
在worker中,原来的__main__
其实叫做__mp_main__
。复制sys.argv
后,工人导入__mp_main__
,导入test
,所以env
设置正确。
虽然 multiprocessing
尽量保持环境相似,但工作进程入口点位于 multiprocessing.spawn
内的某处。那里提到了几个项目:sys.argv
、sys.path
、os.getcwd()
。有关详细信息,请参阅 get_preparation_data()
和 prepare()
。
可以用任务管理器或ps
命令验证工作进程是用不同的参数启动的。
我编写了一个名为 mp.py
的简单脚本来打印 运行 python3 mp.py hello world
的参数。
输出:
29836 process ['C:/xxxx/Whosebug/mp.py'] <module '__main__' from 'C:/xxxx/Whosebug/mp.py'>
29836 my name is main
29836 true main <module '__main__' from 'C:/xxxx/Whosebug/mp.py'>
18464 process ['C:\xxxx\Whosebug\mp.py'] <module '__main__' (built-in)>
18464 worker <module '__mp_main__' from 'C:\xxxx\Whosebug\mp.py'>
mp.py:
from __future__ import annotations
import multiprocessing
import os
import sys
import time
from concurrent.futures import ProcessPoolExecutor
def list_modules(who_am_i):
the_main = sys.modules.get('__main__')
print(os.getpid(), who_am_i, the_main)
def main():
list_modules('true main')
mp_context = multiprocessing.get_context('spawn')
# mp_context = multiprocessing.get_context('fork')
# mp_context = multiprocessing.get_context('forkserver')
with ProcessPoolExecutor(1, mp_context=mp_context) as executor:
executor.submit(list_modules, 'worker').result()
time.sleep(100)
# This message is print when this module is loaded. (none in fork, once in forkserver, multiple times in spawn)
print(os.getpid(), "process", sys.argv, sys.modules.get('__main__'))
if __name__ == '__main__':
# Print once in the main process
print(os.getpid(), "my name is main")
main()
sys.argv
值是否传递到多处理的分支?将 argv 传递给多进程的所有分支的正确方法是什么?
假设我有两个文件:test1.py:
import sys
if len(sys.argv) > 1:
env = sys.argv[1]
else:
env = 'test'
和main_code.py:
from test1 import *
import concurrent.futures
def f():
if env == 'test':
print('bu')
else:
print('not bu')
if __name__ == '__main__':
with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor:
for i in range(2):
executor.submit(f)
我从 cmd main.code.py 调用:python main_code.py zzz
。 sys.argv[1] 变量(即 'zzz')是否在每次调用 executor.submit(f)
时传递,因为它最初是从 text1.py 的导入中获得的?我的困惑来自于 concurrent.futures 基本上通过重新导入所有文件来创建单独的代码线程实例。
在 Windows 上,spawn 上下文是创建工作进程的唯一方法。
sys.argv
被复制到工作进程一次。并非所有文件都重新导入。 unpickle 导入任务函数和参数只需要模块。
在worker中,原来的
__main__
其实叫做__mp_main__
。复制sys.argv
后,工人导入__mp_main__
,导入test
,所以env
设置正确。虽然
multiprocessing
尽量保持环境相似,但工作进程入口点位于multiprocessing.spawn
内的某处。那里提到了几个项目:sys.argv
、sys.path
、os.getcwd()
。有关详细信息,请参阅get_preparation_data()
和prepare()
。可以用任务管理器或
ps
命令验证工作进程是用不同的参数启动的。
我编写了一个名为 mp.py
的简单脚本来打印 运行 python3 mp.py hello world
的参数。
输出:
29836 process ['C:/xxxx/Whosebug/mp.py'] <module '__main__' from 'C:/xxxx/Whosebug/mp.py'>
29836 my name is main
29836 true main <module '__main__' from 'C:/xxxx/Whosebug/mp.py'>
18464 process ['C:\xxxx\Whosebug\mp.py'] <module '__main__' (built-in)>
18464 worker <module '__mp_main__' from 'C:\xxxx\Whosebug\mp.py'>
mp.py:
from __future__ import annotations
import multiprocessing
import os
import sys
import time
from concurrent.futures import ProcessPoolExecutor
def list_modules(who_am_i):
the_main = sys.modules.get('__main__')
print(os.getpid(), who_am_i, the_main)
def main():
list_modules('true main')
mp_context = multiprocessing.get_context('spawn')
# mp_context = multiprocessing.get_context('fork')
# mp_context = multiprocessing.get_context('forkserver')
with ProcessPoolExecutor(1, mp_context=mp_context) as executor:
executor.submit(list_modules, 'worker').result()
time.sleep(100)
# This message is print when this module is loaded. (none in fork, once in forkserver, multiple times in spawn)
print(os.getpid(), "process", sys.argv, sys.modules.get('__main__'))
if __name__ == '__main__':
# Print once in the main process
print(os.getpid(), "my name is main")
main()