
在shell(bash)中,我可以这样做:
MY_ENV_VAR=value ./program_name arg1 arg2 etc &
这将在后台运行program_name,传入“ arg1”,“ arg2”和“ etc”,并带有修改后的环境变量“ MY_ENV_VAR”,其值为“ value”.程序program_name要求将环境变量MY_ENV_VAR设置为适当的值.
如何在Python中做等效的事情?我绝对需要该过程的PID. (我的目的是保持python脚本运行,并同时检查program_name正在执行的某些操作,并且我需要进程ID以确保其仍在运行.)
我试过了:
proc = subprocess.Popen(['MY_ENV_VAR=value', './program_name', 'arg1', 'arg2', 'etc'])
但是,当然,它希望第一个项目是程序,而不是环境变量.
还尝试了:
environ = dict(os.environ)
environ['MY_ENV_VAR'] = 'value'
proc = subprocess.Popen(['./program_name', 'arg1', 'arg2', 'etc', env=environ])
关闭,我想,但没有雪茄.同样,这:
environ = dict(os.environ)
environ['MY_ENV_VAR'] = 'value'
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ)
我想这实际上是在呼应“ $MY_ENV_VAR”,因为没有外壳可以解释它.好的,所以我尝试上面的方法,但是改用以下代码:
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ, shell=True)
很好,很花哨,只是回显的值是空白的(显然不存在).即使它确实起作用,我也会得到外壳的PID,而不是我要启动的实际进程.
我需要使用自定义环境变量启动进程并获取其PID(而不是外壳的PID).有想法吗?
您不希望$MY_ENV_VAR作为要回显的参数. echo程序的环境中将包含MY_ENV_VAR,但echo不会进行任何环境变量扩展.您需要通过外壳将其扩展,甚至无法回显.
这实际上可能与您的实际测试用例无关.您已经在所有测试中将环境变量添加到子进程中,只是echo对该环境变量没有任何作用.如果您的真实程序只需要设置环境变量,则可以完成以下操作:
proc = subprocess.Popen(['./program_name', 'arg1', 'arg2', 'etc'], env=environ)
但是,如果您的程序需要像echo一样替换它,那么您必须在将它们传递给程序之前将其替换为参数.
最简单的方法是给shell一个命令行而不是一个参数列表:
proc = subprocess.Popen('echo "$MY_ENV_VAR"', env=environ, shell=True)
人们会告诉您,您永远不要在子进程中使用命令字符串-这样做的原因是,您始终希望防止shell以可能不安全的方式扩展变量等.在极少数情况下,您希望外壳程序执行其外壳程序操作时,需要命令字符串.
当然,如果在大多数平台上使用外壳程序,最终将获得外壳程序的PID而不是实际程序的PID.没有进行特定于平台的挖掘来枚举shell的子代(或者将整个内容包装在一些简单的sh代码中,从而间接给您子代的PID),就没有办法了. Shell是您正在运行的.
另一种选择是在Python中扩展变量,而不是让Shell来执行.然后,您甚至不需要外壳程序:
proc = subprocess.Popen(['echo', os.path.expandvars('$MY_ENV_VAR')])
…或更简单地说:
proc = subprocess.Popen(['echo', os.environ['MY_ENV_VAR']])
转载注明原文:如何通过subprocess.Popen使用自定义环境变量获取PID? - 乐贴网