如何通过带有自定义环境变量的subprocess.Popen获取PID? [英] How to get PID via subprocess.Popen with custom environment variable?

查看:369
本文介绍了如何通过带有自定义环境变量的subprocess.Popen获取PID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用Python运行带有修改后的环境变量的子进程并获取其PID?我假设subprocess.Popen()沿着正确的轨道...

Using Python, how can I run a subprocess with a modified environment variable and get its PID? I assume subprocess.Popen() is along the right track...

在shell(重击)中,我会这样做:

In shell (bash), I would do this:

MY_ENV_VAR=value ./program_name arg1 arg2 etc &

这在后台运行program_name,传入"arg1","arg2"和"etc",并带有修改后的环境变量"MY_ENV_VAR",其值为"value".程序program_name要求将环境变量MY_ENV_VAR设置为适当的值.

This runs program_name in the background, passing in "arg1" and "arg2" and "etc", with a modified environment variable, "MY_ENV_VAR" with a value of "value". The program program_name requires the environment variable MY_ENV_VAR to be set to the proper value.

如何在Python中做等效的事情?我绝对需要该过程的PID. (我的目的是保持python脚本运行并同时检查program_name正在执行的某些操作,并且我需要进程ID以确保其仍在运行.)

How can do the equivalent thing in Python? I absolutely need the PID of the process. (My intent is to keep the python script running and performing checks on some of the things program_name is doing in the meantime, and I need the process ID to make sure it's still running.)

我尝试过:

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

但是,当然,它希望第一项是程序,而不是环境变量.

But of course, it expects the first item to be the program, not an environment variable.

也尝试过:

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

关闭,我想,但是没有雪茄.同样,这:

Close, I suppose, but no cigar. Similarly, this:

environ = dict(os.environ)
environ['MY_ENV_VAR'] = 'value'
proc = subprocess.Popen(['echo', '$MY_ENV_VAR'], env=environ)

我想这会字面地呼应"$ MY_ENV_VAR",因为没有外壳可以解释它.好的,所以我尝试上面的方法,但是改用下面这行:

This echoes "$MY_ENV_VAR" literally, I suppose because there's no shell to interpret it. Okay, so I try the above but with this line instead:

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

这很好而且很花哨,除了回显的值是空白(显然不存在).即使它确实起作用,我也会得到外壳的PID,而不是我要启动的实际进程.

And that's fine and dandy, except that the value that's echoed is blank (doesn't apparently exist). And even if it did work, I'd get the PID of the shell, not the actual process I'm trying to launch.

我需要使用自定义环境变量启动进程并获取其PID(而不是外壳的PID).想法?

I need to launch a process with a custom environment variable and get its PID (not the PID of the shell). Ideas?

推荐答案

您的最后一个版本非常接近,但还不足够.

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

您不希望$MY_ENV_VAR作为echo的参数. echo程序的环境中将包含MY_ENV_VAR,但是echo不会进行任何env变量扩展.您需要先由shell对其进行扩展,然后再将其扩展到echo.

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.

这实际上可能与您的实际测试用例无关.您已经 在所有测试中都将环境变量添加到了子进程中,只是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)

但是,如果您的程序需要像echo那样被替换,那么您必须将其替换为参数之前,然后它们才能传递给您的程序.

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.

最简单的方法是为shell提供命令行而不是参数列表:

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)

人们会告诉您,切勿在subprocess中使用命令字符串-这样做的原因是,您始终希望以某种不安全的方式阻止shell扩展变量等. .在极少数情况下,您想要执行外壳程序的外壳操作时,您会想要命令字符串.

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.

当然,如果您使用外壳,则在大多数平台上,最终将获得外壳的PID,而不是实际程序的PID.没有进行特定于平台的挖掘来枚举Shell的子代(或者将整个内容包装在一些简单的sh代码中,这些代码间接为您提供子代的PID),就没有办法了. Shell是您正在运行的.

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.

另一种替代方法是在Python中扩展变量,而不是使Shell做到这一点.然后,您甚至根本不需要外壳:

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')])

…,或者甚至更简单:

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

这篇关于如何通过带有自定义环境变量的subprocess.Popen获取PID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆