子进程应该如何用于具有heredocuments和多个管道的命令?

2024-05-23 18:23:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我如何使用subprocess而不是os在Bash中运行如下命令?公司名称:

import os
text     = "~|||-:this is text:-|||~"
fileName = "sound.wav"
command  =\
    "IFS= read -d \'\' text <<EOF\n" +\
    text + "\n" +\
    "EOF\n" +\
    "echo \"${text}\" | sed -e 's/\([[:punct:]]\)//g' | text2wave -scale 1 -o " + fileName
os.system(command)

理想情况下,这将在Bash中得到以下结果:

^{pr2}$

请注意,我在命令中同时使用here文档和多个管道。我知道我不需要在命令中进行sed处理,但是我正在特别尝试使用subprocess在Bash中如何运行这样一个命令。在

目前,我在subprocess命令过程中看到了“pipes”的一些实现,但是与简单的竖线符号相比,这些实现非常冗长。我可以想象这样的场景会变成噩梦般的多个管道。至于这里的文档,我不知道如何用subprocess来实现它们。我会珍惜你可能有的任何关于实现这一点的指导。在

如果您感兴趣,text2wave程序是Festival的一部分。在


Tags: text文档import命令名称bash管道os
3条回答

如果外壳很适合您的问题,那么一定要使用外壳。在

您有时希望将某些东西移植到Python的原因至少对我来说是出于更好的控制:您希望能够捕捉到管道中间的错误(在您的shell脚本中是这样的),或者您希望在处理过程的中途将结果保存在某个地方,这在shell中做起来很麻烦,因为管道是友好的一维的。在

如果你真的坚持,那么你提到的资源(但没有链接)是通常的做法;但由于上述原因,这并不特别“常见”。在

下面是一个不使用shell的示例,改编自this question

from subprocess import Popen, PIPE

input="""
~|||-:this is text:-|||~
"""
p1 = Popen(['sed', r's/\([[:punct:]]\)//g'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
p2 = Popen(['text2wave', '-scale', '1', '-o', fileName],
    stdin=p1.stdout, stdout=PIPE, stderr=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p1.stdin.write(input)
p1.stdin.close()
output, error = p2.communicate()
p1.wait()
print('status: {0}\nOutput: {1}\nError:{2}'.format(p2.returncode, output, error))

我确信这可以扩展到两个以上的子进程,但我也坦率地相当肯定,如果你真的需要弄清楚的话,你做的是错误的。在

。。。而且,正如在评论中已经指出的,sed部分可以很容易地被simple Python snippet替换

^{pr2}$

还要注意Python多行字符串如何替换here文档。在

这里docs和pipes(|)是shell的属性。如果要逐字运行命令,请使用shell=True

from subprocess import check_call

check_call(r"""IFS= read -d '' text <<EOF
~|||-:this is text:-|||~
EOF
echo "${text}" | sed -e 's/\([[:punct:]]\)//g' | text2wave -scale 1 -o sound.wav
""", shell=True)

作为@tripleee said,可以用Python实现部分甚至整个命令。在

带有os.popen的演示: 公司名称:

print os.popen(r"""
    /bin/bash<<EOF
shell line 1...
shell line 2...
shell line 3...
EOF
""").read()

或者

^{pr2}$

相关问题 更多 >