Python子进程参数带引号
我想从Python中运行一个叫做http://mediaarea.net/en/MediaInfo的命令行工具。这个工具接受一些参数,使用起来很简单。
*简单用法: *
# verbose all info
MediaInfo.exe test.mp4
模板用法:
# verbose selected info from csv
MediaInfo.exe --inform="file://D:\path\to\csv\template.csv" test.mp4
我想用模板参数来运行它。我可以在命令提示符(CMD)中成功使用上面的命令。它运行得很好,我可以在DOS窗口中看到我选择的输出。
但是当我尝试从Python中运行它时,它输出了所有的信息,而忽略了我作为参数提供的CSV文件。有人能解释一下为什么吗?是因为引号的问题吗?
注意: 如果CSV的路径不正确或者CSV文件无效,MediaInfo会输出所有的信息,这正是现在发生的情况。
#App variable is full path to MediaInfo.exe
#filename variable is full path to media file
proc = subprocess.Popen([App ,'--inform="file://D:\path\to\csv\template.csv"',filename],shell=True,stderr=subprocess.PIPE, stdout=subprocess.PIPE)
return_code = proc.wait()
for line in proc.stdout:
print line
2 个回答
0
如果你用 print
打印你的参数,你可能会看到哪里出错了:
>>> print '--inform="file://D:\path\to\csv\template.csv"'
--inform="file://D:\path o\csv emplate.csv"
问题在于 \
这个符号表示特殊字符。如果你在字符串前面加上 "r" 这个字母,这些特殊字符就不会被转义了:
>>> print r'--inform="file://D:\path\to\csv\template.csv"'
--inform="file://D:\path\to\csv\template.csv"
1
在Windows系统上,你可以直接把命令作为字符串传递,也就是原样传递:
from subprocess import check_output
cmd = r'MediaInfo.exe --inform="file://D:\path\to\csv\template.csv" test.mp4'
out = check_output(cmd)
注意:r''
-- 这里用的是原始字符串字面量,这样可以避免把'\t'
解释成一个制表符,而是把它当作两个字符(反斜杠和t
)来处理。
另外,如果你设置了stdout=PIPE, stderr=PIPE
,那么你需要同时读取这两个输出流,并且要在调用p.wait()
之前完成,否则如果命令输出的内容太多,就可能会出现死锁的情况。
如果把命令作为字符串传递有效的话,你也可以尝试用列表作为参数:
from subprocess import check_output
from urllib import pathname2url
cmd = [app, '--inform']
cmd += ['file:' + pathname2url(r'D:\path\to\csv\template.csv')]
cmd += [filename]
out = check_output(cmd)
你能写个例子说明你提到的
p.wait()
死锁吗?
这很简单。只需要在子进程中产生大量输出:
import sys
from subprocess import Popen, PIPE
#XXX DO NOT USE, IT DEADLOCKS
p = Popen([sys.executable, "-c", "print('.' * (1 << 23))"], stdout=PIPE)
p.wait() # <-- this never returns unless the pipe buffer is larger than (1<<23)
assert 0 # unreachable