subprocess.Popen("echo $ HOME" ...和subprocess.Popen(["echo","$ HOME"]之间有什么区别 [英] What's the difference between subprocess.Popen("echo $HOME"... and subprocess.Popen(["echo", "$HOME"]
问题描述
我无法获得与bash相关或python子进程的信息,但结果有所不同:
I cannot get it it's bash related or python subprocess, but results are different:
>>> subprocess.Popen("echo $HOME", shell=True, stdout=subprocess.PIPE).communicate()
(b'/Users/mac\n', None)
>>> subprocess.Popen(["echo", "$HOME"], shell=True, stdout=subprocess.PIPE).communicate()
(b'\n', None)
为什么第二次只是换行符?争论在哪里消失?
Why in second time it's just newline? Where argument are falling off?
推荐答案
subprocess.Popen()
的第一个参数告诉系统要运行什么.
The first argument to subprocess.Popen()
tells the system what to run.
当它是列表时,您需要使用shell=False
.它恰好在Windows中如您所愿地起作用.但是在类Unix平台上,您只是传递了许多通常会被忽略的参数.实际上,
When it is a list, you need to use shell=False
. It coincidentally happens to work as you hope in Windows; but on Unix-like platforms, you are simply passing in a number of arguments which will typically get ignored. Effectively,
/bin/sh -c 'echo' '$HOME'
这只会导致第二个参数不被使用(在这里我使用单引号来强调它们只是静态字符串).
which simply causes the second argument to not be used for anything (where I use single quotes to emphasize that these are just static strings).
以我的拙见,在这种情况下,Python应该抛出一个错误.在Windows上也是如此.这是一个错误,应该捕获并报告.
In my humble opinion, Python should throw an error in this case. On Windows, too. This is an error which should be caught and reported.
(在相反的情况下,虽然指定了shell=False
,但您传递的字符串不是有效命令的名称,但最终还是会得到一个错误,并且即使您对此有一个模糊的想法也很有意义发生了什么.)
(In the opposite case, where shell=False
is specified but the string you pass in is not the name of a valid command, you will get an error eventually anyway, and it makes sense if you have even a vague idea of what's going on.)
如果您真的知道自己在做什么,则可以使第一个参数访问后续参数;例如
If you really know what you are doing, you could cause the first argument to access subsequent arguments; for example
/bin/sh -c 'printf "%s\n" "$@"' 'ick' 'foo' 'bar' 'baz'
将在单独的行上打印foo
,bar
和baz
. (零"参数-这里是'ick'
-用于填充$0
.)但这只是一个晦涩的推论;不要尝试将其用于任何用途.
would print foo
, bar
, and baz
on separate lines. (The "zeroth" argument - here, 'ick'
- is used to populate $0
.) But this is just an obscure corollary; don't try to use this for anything.
此外,如果只想运行命令,则不应使用subprocess.Popen()
. subprocess.run()
文档将更详细地告诉您这一点.使用text=True
,您将得到一个字符串而不是字节.
As a further aside, you should not use subprocess.Popen()
if you just want a command to run. The subprocess.run()
documentation tells you this in some more detail. With text=True
you get a string instead of bytes.
result = subprocess.run('echo "$HOME"', shell=True,
text=True, capture_output=True, check=True)
print(result.stdout, result.stderr)
当然,os.environ['HOME']
允许您从Python内部访问$HOME
的值.这也允许您shell=True
,如果可以的话,通常应该这样做.
And of course, os.environ['HOME']
lets you access the value of $HOME
from within Python. This also allows you to avoid shell=True
which you usually should if you can.
这篇关于subprocess.Popen("echo $ HOME" ...和subprocess.Popen(["echo","$ HOME"]之间有什么区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!