subprocess.Popen("echo $ HOME" ...和subprocess.Popen(["echo","$ HOME"]之间有什么区别 [英] What's the difference between subprocess.Popen("echo $HOME"... and subprocess.Popen(["echo", "$HOME"]

查看:207
本文介绍了subprocess.Popen("echo $ HOME" ...和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'

将在单独的行上打印foobarbaz. (零"参数-这里是'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屋!

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