How to get PID via subprocess.Popen with custom environment variable?

感情迁移 提交于 2019-12-05 18:55:37

Your last version is very close, but not quite there.

You don't want $MY_ENV_VAR to be an argument to echo. The echo program will have MY_ENV_VAR in its environment, but echo doesn't do any env variable expansion. You need it to be expanded by the shell, before it even gets to echo.

This may actually have nothing to do with your real-life test case. You already are getting the environment variable to the child process in all of your tests, it's just that echo doesn't do anything with that environment variable. If your real program just needs the environment variable to be set, you're done:

proc = subprocess.Popen(['./program_name', 'arg1', 'arg2', 'etc'], env=environ)

But if your program needs it to be substituted, like echo, then you have to substitute it into the arguments before they get passed to your program.

The easiest way to do that is to just give the shell a command line instead of a list of arguments:

proc = subprocess.Popen('echo "$MY_ENV_VAR"', env=environ, shell=True)

People will tell you that you should never use a command string in subprocess—but the reason for that is that you always want to prevent the shell from expanding variables, etc., in a way that could be insecure/etc. On the rare occasions when you want the shell to do its shelly things, you want a command string.

Of course if you use a shell, on most platforms, you're going to end up getting the PID of the shell rather than the PID of the actual program. Short of doing some platform-specific digging to enumerate the shell's children (or wrapping the whole thing in some simple sh code that gives you the child's PID indirectly), there's no way around that. The shell is what you're running.

Another alternative is to expand the variables in Python instead of making the shell do it. Then you don't even need a shell:

proc = subprocess.Popen(['echo', os.path.expandvars('$MY_ENV_VAR')])

… or, even more simply:

proc = subprocess.Popen(['echo', os.environ['MY_ENV_VAR']])

here's a program that spits out the current environment.

#!/usr/bin/env python
##program_name
import os
for k,v in os.environ.iteritems():
    print k, '=', v

Here's a program that calls the other program, but first changes the environment

#!/usr/bin/env python
import subprocess, os
newenv = os.environ.copy()
newenv['MY_ENV_VAR'] = 'value'
args = ['./program_name', 'arg1', 'arg2', 'etc']
proc = subprocess.Popen(args, env=newenv)
pid = proc.pid
proc.wait()
print 'PID =', pid
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!