python - 在衍生进程中读取 OS 环境变量
问题描述
这与上一个问题类似,但用于multiprocessing
代替subprocess
. 似乎动态更改PYTHONHASHSEED
在使用时没有效果multiprocessing
,不像subprocess
:
#check_environ.py
import os, multiprocessing, subprocess, sys
s = 'hello'
print('parent', os.getenv('PYTHONHASHSEED'), hash(s))
if len(sys.argv) > 1:
os.environ['PYTHONHASHSEED'] = sys.argv[1]
subprocess.call(['python', '-c', "import os;print('subprocess', os.getenv('PYTHONHASHSEED'), hash('{}'))".format(s)])
multiprocessing.Process(target=lambda:print('multiprocessing', os.getenv('PYTHONHASHSEED'), hash(s))).start()
样品运行:
# explicit PYTHONHASHSEED for subprocess/multiprocessing
$ python check_environ.py 12
parent None 4472558296122225349
subprocess 12 -8207222429063474615
multiprocessing 12 4472558296122225349
# random PYTHONHASHSEED for subprocess/multiprocessing
$ python check_environ.py
parent None 7990499464460966677
subprocess None 1081030409066486350
multiprocessing None 7990499464460966677
所以无论如何,multiprocessing
哈希使用与父级相同的种子。有没有办法强制multiprocessing
使用不同的哈希种子产生子进程?
解决方案
您可以通过使用“fork”以外的其他启动方法来创建进程。您的操作系统正在使用 fork(您没有PicklingError
使用 lambda 作为目标)。
如果可用,您可以将启动方法更改为“spawn”(Windows 上的默认选项和唯一选项)multiprocessing.set_start_method('spawn')
或“forkserver”。使用 获取所有可用的方法multiprocessing.get_all_start_methods()
。
#check_environ.py
import sys, os, subprocess
import multiprocessing as mp
def show(s):
print('multiprocessing', os.getenv('PYTHONHASHSEED'), hash(s))
if __name__ == '__main__':
mp.set_start_method('spawn')
s = 'hello'
print('parent', os.getenv('PYTHONHASHSEED'), hash(s))
if len(sys.argv) > 1:
os.environ['PYTHONHASHSEED'] = sys.argv[1]
cmd = "import os; " \
"print('subprocess', os.getenv('PYTHONHASHSEED'), hash('{}'))"
subprocess.call(['python', '-c', cmd.format(s)])
p = mp.Process(target=show, args=(s,))
p.start()
p.join()
终端输出:
$ python check_environ.py 12
parent None 4279361553958749032
subprocess 12 -8207222429063474615
multiprocessing 12 -8207222429063474615
如果您需要多次在启动方法之间切换,请使用上下文对象来设置启动方法:
ctx = mp.get_context('spawn')
p = ctx.Process(target=foo, args=(var,))
但是要准备好为使用除 fork 之外的另一种启动方法付出巨大的时间损失。我在运行 Ubuntu 18.04 的机器上启动了一个 python 进程的基准测试:
- 分叉 1.59 毫秒
- 分叉服务器 289.83 毫秒
- 产生 348.20 毫秒
但这不一定与您的用例相关。
推荐阅读
- vb.net - 尝试使用 Rbutton VB.Net 创建一个简单的 while 循环
- r - 从字符串中删除特殊字符和空格
- python - 关于限制的切片列表
- angular - 在Angular 11中显示选定的项目名称而不是选定的ID
- database-design - 使用 dynamodb 获取每条评论/消息的相关数据
- angular - 除了第一个请求之外的每个请求都失败,并显示 'idx10503 签名验证失败。令牌没有孩子' 除了第一个请求
- pivot - 松树脚本指示器:枢轴点回头看 1 而不是 5
- wpf - 设置wpf图片的来源
- apache - Apache2:预期但看到
- git - Git 在暂存时给出输入/输出错误。无法写入松散的目标文件