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)

我从 c​​md main.code.py 调用:python main_code.py zzz。 sys.argv[1] 变量(即 'zzz')是否在每次调用 executor.submit(f) 时传递,因为它最初是从 text1.py 的导入中获得的?我的困惑来自于 concurrent.futures 基本上通过重新导入所有文件来创建单独的代码线程实例。

在 Windows 上,spawn 上下文是创建工作进程的唯一方法。

  1. sys.argv 被复制到工作进程一次。

  2. 并非所有文件都重新导入。 unpickle 导入任务函数和参数只需要模块。

  3. 在worker中,原来的__main__其实叫做__mp_main__。复制sys.argv后,工人导入__mp_main__,导入test,所以env设置正确。

  4. 虽然 multiprocessing 尽量保持环境相似,但工作进程入口点位于 multiprocessing.spawn 内的某处。那里提到了几个项目:sys.argvsys.pathos.getcwd()。有关详细信息,请参阅 get_preparation_data()prepare()

  5. 可以用任务管理器或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()