我有很多需要在Python脚本中执行的Shell命令。我知道不应该像这里所提到的那样使用shell=true,而是可以像这里所提到的那样,在命令中使用标准输出和输入。
但问题是我的Shell命令非常复杂,充满了管道操作,因此我想编写一个通用的方法供我的脚本使用。
我下面做了一个小测试,但在打印结果后就一直挂起(我简化了代码才放在这里)。请问有人能告诉我:
- 为什么会挂起。
- 是否有更好的方法来实现这个功能。
谢谢。
PS:这只是一个大型Python项目的一小部分,我之所以尝试这样做,是因为有业务需求。感谢。
#!/usr/bin/env python3
import subprocess as sub
from subprocess import Popen, PIPE
import shlex
def exec_cmd(cmd,p=None,isFirstLoop=True):
if not isFirstLoop and not p:
print("Error, p is null")
exit()
if "|" in cmd:
cmds = cmd.split("|")
while "|" in cmd:
# separates what is before and what is after the first pipe
now_cmd = cmd.split('|',1)[0].strip()
next_cmd = cmd.split('|',1)[-1].strip()
try:
if isFirstLoop:
p1 = sub.Popen(shlex.split(now_cmd), stdout=PIPE)
exec_cmd(next_cmd,p1,False)
else:
p2 = sub.Popen(shlex.split(now_cmd),stdin=p.stdout, stdout=PIPE)
exec_cmd(next_cmd,p2,False)
except Exception as e:
print("Error executing command '{0}'.\nOutput:\n:{1}".format(cmd,str(e)))
exit()
# Adjust cmd to execute the next part
cmd = next_cmd
else:
proc = sub.Popen(shlex.split(cmd),stdin=p.stdout, stdout=PIPE, universal_newlines=True)
(out,err) = proc.communicate()
if err:
print(str(err).strip())
else:
print(out)
exec_cmd("ls -ltrh | awk '{print $9}' | wc -l ")
shell=True
时的问题... 这段代码并没有好到哪里去。其次,如果你使用stdout=PIPE
创建一个管道,然后传递stdin=proc.stdout
来使用同一个管道,这是连接程序的更好方法。但这需要一些思考。 - Dietrich Epp