从python代码执行Unix命令
diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)
我想从Python代码执行上述命令。以下是我写的代码。从python代码执行Unix命令
cmd = "diff -u < (echo 'aba'| fold -w1) < (echo 'abaa' | fold -w1)"
os.system(cmd)
运行上面的代码,我得到了sh: 1: Syntax error: "(" unexpected
错误。据我所知,unix os无法解析大括号内的echo命令。
帮我解决这个错误。
命令在bash
中正常运行,但os.system()
正在执行/bin/sh
中的命令。
>>> os.system('echo $0')
sh
0
时/bin/sh
执行的命令失败:
[[email protected] ~]$ /bin/sh
sh-4.3$ diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)
sh: syntax error near unexpected token `('
sh-4.3$
您可以明确地在bash
运行的命令是这样的:
>>> os.system("""bash -c 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)'""")
--- /dev/fd/63 2017-02-26 09:18:14.633395225 +1100
+++ /dev/fd/62 2017-02-26 09:18:14.633395225 +1100
@@ -1,3 +1,4 @@
a
b
a
+a
256
既然你可以用检查可能对你通常能够输出的命令感兴趣使用subprocess.check_output()
来执行该命令并收集其输出。不幸的是,diff
在检测到输入文件中的差异时会返回非零退出代码,因此可以防止简单地使用check_output
。您可以通过管道diff
的输出通过cat
欺骗:
>>> from subprocess import check_output
>>> output = check_output(['bash', '-c', 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1) | cat'])
>>> print(output)
b'--- /dev/fd/63\t2017-02-26 10:02:56.814044987 +1100\n+++ /dev/fd/62\t2017-02-26 10:02:56.814044987 +1100\[email protected]@ -1,3 +1,4 @@\n a\n b\n a\n+a\n'
>>> print(str(output, encoding='utf8'))
--- /dev/fd/63 2017-02-26 10:02:56.814044987 +1100
+++ /dev/fd/62 2017-02-26 10:02:56.814044987 +1100
@@ -1,3 +1,4 @@
a
b
a
+a
首先,os.system()
是有利于subprocess.call(cmd, shell=True)
气馁。这是值得了解的,因为有很多的附加细节的subprocess
文档中,包括shell=True
参数的描述(强调):
在POSIX与
shell=True
,该壳默认为/bin/sh
.... POPEN不等价的:Popen(['/bin/sh', '-c', args[0], args[1], ...])
所以,现在我们知道为什么你的命令不起作用 - 这不是调用猛砸。作为mhawke建议你应该改为调用bash
直接,但你应该更喜欢subprocess
模块在os.system()
:
>>> subprocess.call(['/bin/bash', '-c', 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)'])
--- /dev/fd/63 2017-02-25 14:32:49.000000000 -0800
+++ /dev/fd/62 2017-02-25 14:32:49.000000000 -0800
@@ -1,3 +1,4 @@
a
b
a
+a
1
需要注意的是,因为我们明确地调用Bash shell中,我们不需要shell=True
,而且由于我们告诉Bash调用的命令是一个我们不需要反复逃避的参数,例如与mhawke一样,"""
。
一旦你验证了该命令的工作,你可能想从简单地调用call()
到其他subprocess
功能之一是更多的脚本友好的,如run()
,它返回一个CompletedProcess
对象,你可以检查移开。
正如让 - 弗朗索瓦·法布尔建议你可以做很多更强大的东西与subprocess
,以及包括启动<()
替换为单独的进程,并将它们通过管道进入呼叫diff
,从而避免了需要调用bash
或写的Bash语法在Python中。它更冗长,但更具可扩展性和可维护性。
和便携式,你只需要在窗口上安装'diff'&'fold'。 –
,或者你可以
import subprocess
cmd = """bash -c 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)'"""
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ps.communicate()[0]
如果你没有全部使用3个子进程对象并删除'shell = True'部分,那么使用'subprocess'而不是'os.system()'有什么意义? –
@ Jean-FrançoisFabre“最好的方法是使用与管道连接在一起的3个Popen对象。”你是这个意思吗? – Juggernaut
最好的办法是使用与管道链接在一起3'Popen'对象。 –
@ Jean-FrançoisFabre:这是真的,但这取决于你的观点。 OP询问'os.system()'。 – mhawke
我不是在批评你的答案,而是问题:) +1是我的。我应该评论这个问题,而不是答案。我不能责怪你不想用python编写3个管道! –