subprocess 应该如何用于具有 here-documents 和多个管道的命令?
How should subprocess be used for commands featuring here-documents and multiple pipes?
如何在 Bash 中使用 subprocess
而不是 os
到 运行 的命令如下?:
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 中评估为以下内容:
IFS= read -d '' text <<EOF
~|||-:this is text:-|||~
EOF
echo "${text}" | sed -e 's/\([[:punct:]]\)//g' | text2wave -scale 1 -o sound.wav
请注意,我在命令中同时使用了 here-document 和多个管道。我知道我不需要在命令中进行 sed 处理,但是我正在尝试专门查看这样的命令在 Bash 中如何使用 subprocess
运行 .
目前,我在subprocess
命令程序中看到了一些'pipes'的实现,但与简单的竖线符号相比,这些实现非常冗长。我可以想象这种情况会因多个管道而变得噩梦般。至于这里的文档,我不知道如何用 subprocess
来实现它们。我会重视您可能拥有的有关实施此功能的任何指导。
程序 text2wave 是 Festival 的一部分,如果您有兴趣的话。
Here-docs 和管道 (|
) 是 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)
与一样,部分甚至全部命令都可以在Python中实现。
如果 shell 很适合您的问题,那么一定要使用 shell.
你有时想要将某些东西移植到 Python 的原因至少对我来说是出于更好的控制:你希望能够在(你的 shell 脚本是) 管道,或者你想在处理的中途保留结果,这在 shell 中很麻烦,因为管道是一维的。
如果您真的坚持,那么您提到(但不 link )的资源就是通常的做法;但由于上述原因,这并不是特别 "common".
这是一个不使用 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;
from string import punctuation
input = input.translate(None, punctuation)
另请注意 Python 多行字符串如何替换此处的文档。
os.popen
演示:
:
print os.popen(r"""
/bin/bash<<EOF
shell line 1...
shell line 2...
shell line 3...
EOF
""").read()
或
subprocess.Popen("""
/bin/bash<<EOF
shell line 1...
shell line 2...
shell line 3...
EOF
""", shell=True)
如何在 Bash 中使用 subprocess
而不是 os
到 运行 的命令如下?:
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 中评估为以下内容:
IFS= read -d '' text <<EOF
~|||-:this is text:-|||~
EOF
echo "${text}" | sed -e 's/\([[:punct:]]\)//g' | text2wave -scale 1 -o sound.wav
请注意,我在命令中同时使用了 here-document 和多个管道。我知道我不需要在命令中进行 sed 处理,但是我正在尝试专门查看这样的命令在 Bash 中如何使用 subprocess
运行 .
目前,我在subprocess
命令程序中看到了一些'pipes'的实现,但与简单的竖线符号相比,这些实现非常冗长。我可以想象这种情况会因多个管道而变得噩梦般。至于这里的文档,我不知道如何用 subprocess
来实现它们。我会重视您可能拥有的有关实施此功能的任何指导。
程序 text2wave 是 Festival 的一部分,如果您有兴趣的话。
Here-docs 和管道 (|
) 是 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)
与
如果 shell 很适合您的问题,那么一定要使用 shell.
你有时想要将某些东西移植到 Python 的原因至少对我来说是出于更好的控制:你希望能够在(你的 shell 脚本是) 管道,或者你想在处理的中途保留结果,这在 shell 中很麻烦,因为管道是一维的。
如果您真的坚持,那么您提到(但不 link )的资源就是通常的做法;但由于上述原因,这并不是特别 "common".
这是一个不使用 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;
from string import punctuation
input = input.translate(None, punctuation)
另请注意 Python 多行字符串如何替换此处的文档。
os.popen
演示:
:
print os.popen(r"""
/bin/bash<<EOF
shell line 1...
shell line 2...
shell line 3...
EOF
""").read()
或
subprocess.Popen("""
/bin/bash<<EOF
shell line 1...
shell line 2...
shell line 3...
EOF
""", shell=True)