如何向subprocess.Popen提供多行命令?
我需要通过Python的subprocess.Popen来运行一个多行的dtrace脚本,我尝试了这样做……下面是我在Python中写的代码片段,但这并没有成功,处理这种模板的正确方法是什么呢?
cmd = "/usr/sbin/dtrace -n '
#pragma D option quiet
profile:::profile-1001hz
/arg0/
{
\@pc[arg0] = count();
}
dtrace:::END
{
printa("%a %\@d\\n", \@pc);
}'"
def execute_hotkernel():
proc = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(output, error) = proc.communicate()
print output
使用引号并不能把多行命令包裹在cmd
里。当我尝试运行时,出现了一个错误:SyntaxError: EOL while scanning string literal
。
3 个回答
1
这个错误是因为你需要用三个"
来表示多行字符串。
s = """#pragma D option quiet
profile:::profile-1001hz
/arg0/
{
\@pc[arg0] = count();
}
dtrace:::END
{
printa("%a %\@d\\n", \@pc);
}"""
不过我建议你把脚本写到一个文件里,然后用Popen来运行它。
subprocess.Popen(['/usr/sbin/dtrace', 'script_you_have_just_created.td'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
总之,如果脚本没有变化,就没必要在你的代码里把它保存在一个变量里。
2
arg3 = '''
#pragma D option quiet
profile:::profile-1001hz
/arg0/
{
\@pc[arg0] = count();
}
dtrace:::END
{
printa("%a %\@d\\n", \@pc);
}
'''
proc = subprocess.Popen(['/usr/sbin/dtrace', '-n', arg3], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
Popen
的第一个参数是一个参数列表,除非你设置了shell=True
,但这样做不太推荐。
2
这里有几个问题。首先,SyntaxError: EOL while scanning string literal
这个错误是因为你试图用一个双引号来创建一个多行字符串,这在Python中是不合法的。你可以使用三个双引号来实现:
cmd = """/usr/sbin/dtrace -n '
#pragma D option quiet
...
"""
第二个问题是,默认情况下,subprocess.Popen
需要一个字符串数组,而不是一个用空格分开的命令。如果你想让它接受像你现在这样的一串命令,可以给Popen
加上一个参数shell=True
。另外,你也可以把命令拆开,把dtrace脚本放在你的多行字符串里:
dtrace_script = """#pragma D option quiet
profile:::profile-1001hz
/arg0/
{
\@pc[arg0] = count();
}
dtrace:::END
{
printa("%a %\@d\\n", \@pc);
}
"""
...
subprocess.Popen(['/usr/sbin/dtrace', '-n', dtrace_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)