为什么 args 是序列时 subprocess.Popen 不工作?
我在使用subprocess.Popen的时候遇到了问题,特别是当给args参数传递一个序列时。
举个例子:
import subprocess
maildir = "/home/support/Maildir"
这个是可以正常工作的(它会打印出/home/support/Maildir目录的正确大小):
size = subprocess.Popen(["du -s -b " + maildir], shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]
print size
但是,这个就不行(你可以试试):
size = subprocess.Popen(["du", "-s -b", maildir], shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]
print size
到底哪里出了问题呢?
3 个回答
1
应该是 ["du", "-s", "-b", maildir]
5
根据文档,
在Unix系统中,当使用shell=True时:如果args是一个字符串,那么它就是要通过命令行执行的命令字符串。如果args是一个序列(比如列表),那么第一个项目就是命令字符串,后面的项目会被当作额外的命令参数。
所以,可以尝试
subprocess.Popen("du -s -b " + maildir, ...
或者
subprocess.Popen(["du","-s","-b",maildir], ...
12
来自文档
在Unix系统中,当设置为shell=True时:[…] 如果args是一个序列,第一个项目指定了命令字符串,任何额外的项目会被当作额外的参数传给shell本身。也就是说,Popen的作用相当于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
在你的情况下,这意味着:
Popen(['/bin/sh', '-c', 'du', '-s', '-b', maildir])
这表示 -s
、-b
和 maildir
是被shell当作选项来理解的,而不是被 du
理解(你可以在命令行试试!)。
因为在你的情况下其实不需要 shell=True
,所以你可以直接把它去掉:
size = subprocess.Popen(['du', '-s', '-b', maildir],
stdout=subprocess.PIPE).communicate()[0].split()[0]
另外,你也可以继续使用你原来的方法,但那样的话就不需要用列表。你还需要注意目录名中的空格:
size = subprocess.Popen('du -s -b "%s"' % maildir, shell=True,
stdout=subprocess.PIPE).communicate()[0].split()[0]