Python subprocess Popen参数区别

0 投票
2 回答
3377 浏览
提问于 2025-04-16 07:48

这两个代码块有什么区别呢?

subprocess.Popen(['cat','/path/to/file'], stdout=subprocess.PIPE, shell=True)

subprocess.Popen(['cat '+'/path/to/file'], stdout=subprocess.PIPE, shell=True)

?我在使用ipython的时候遇到这个问题。

第一个代码块运行的时候,ipython就卡住了。可能不是完全卡住,但速度明显慢了很多。

而第二个代码块运行得就挺正常的。

我就是搞不懂为什么会这样。

2 个回答

0

我测试了一些示例,发现第一个示例在ipython中返回了一个Popen对象,而第二个示例也返回了一个Popen对象,但打印出了cat: /path/to/file: No such file or directory的错误信息。

我喜欢尽量避免在使用subprocess.Popen时加上shell=True,而是使用像['x', '--version']这样的列表,这样就不需要处理路径名中可能出现的特殊字符,比如反引号之类的麻烦。

在对pymp.py的一个补丁中,我把:

p = subprocess.Popen(['mplayer -slave -quiet \'' + target + '\' -include \'' + MPLAYERCONFFILE + '\' 2>/dev/null'], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

改成了:

devnull = open('/dev/null', 'w')
p = subprocess.Popen(['mplayer', '-slave', '-quiet', target, '-include', MPLAYERCONFFILE], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=devnull)
4

第一个情况实际上只是运行了 cat 命令(因为当你使用 shell = True 时,命令的解析方式),所以它会一直挂着,因为它在等待输入。第二个情况是运行 cat /path/to/file。你可以通过以下方式查看这个情况:

>>> subprocess.Popen(['ls', '-l'])
<subprocess.Popen object at 0x10048bdd0>
>>> total 8
-rw-------  1 root     wheel  652 Nov 29 09:07 000d94cfc78b4
srwxr-xr-x  1 nbastin  wheel    0 Nov 29 09:06 ics179
srwxr-xr-x  1 nbastin  wheel    0 Nov 29 09:06 icssuis501
drwx------  3 nbastin  wheel  102 Nov 29 09:06 launch-3ZniHd
drwx------  3 nbastin  wheel  102 Nov 29 09:06 launch-8QRgz2
drwx------  3 nbastin  wheel  102 Nov 29 09:06 launch-M5ppWp
drwx------  3 nbastin  wheel  102 Nov 29 09:06 launchd-137.ztQAmI
drwx------  2 nbastin  wheel   68 Nov 29 09:57 ssh-LreGlOZPAR

而如果你使用 shell = True 的话,效果就不一样了:

>>> subprocess.Popen(['ls', '-l'], shell = True)
<subprocess.Popen object at 0x10048bd90>
>>> 000d94cfc78b4       ics179          icssuis501      launch-3ZniHd       launch-8QRgz2       launch-M5ppWp       launchd-137.ztQAmI  ssh-LreGlOZPAR

如果你设置了 shell = True,那么传递一个列表作为 args 是无法得到你想要的效果的——你需要传递一个字符串。

撰写回答