Python 子进程与 heredoc
我在玩Python的subprocess模块,尝试了一些例子,但我似乎无法让heredoc语句正常工作。
这是我正在尝试的一个简单例子:
import subprocess
a = "A String of Text"
p = subprocess.Popen(["cat", "<<DATA\n" + a + "\nDATA"])
当我运行上面的代码时,我得到了以下错误:
cat: <<DATA\nA String of Text\nDATA: No such file or directory
我是不是做错了?这真的可行吗?如果可以的话,我该怎么做呢?
更新
我想说的是,这种做法在真正的Python程序中是不应该使用的,因为有更好的方法来实现这个功能。
4 个回答
4
正如其他人提到的,你需要在一个命令行窗口中运行它。使用Popen这个工具时,加上一个参数shell=True就能很简单地做到这一点。我得到了以下输出:
>>> import subprocess
>>> a = "A String of Text"
>>> p = subprocess.Popen("cat <<DATA\n" + a + "\nDATA", shell=True)
>>> A String of Text
>>> p.wait()
0
4
你正在把一些 shell 语法当作参数传给 cat
程序。你可以试试这样做:
p = subprocess.Popen(["sh", "-c", "cat <<DATA\n" + a + "\nDATA"])
不过,这个想法本身就不太对。你应该使用 Python 的功能,而不是在你的 Python 脚本里调用 shell 脚本。
而且在这个特定的情况下,shell 的 heredoc 语法会把变量的值插入进去,所以你需要对 a
里面的所有文本进行转义,并确保里面没有 DATA
这一行。
如果用 Python 来实现,我觉得最接近的想法是(假设你不只是想用 print(a)
输出内容;-))把变量的值传给一个新进程的标准输入:
p = subprocess.Popen(["program", ...], stdin=subprocess.PIPE)
p.communicate(a)
6
Shell中的“heredoc”是一个功能,允许你在命令中直接写入多行文本。不过,subprocess.Popen
默认情况下并不会通过shell来运行你的命令,所以这种写法是行不通的。
不过,既然你已经在使用管道了,就没必要再用shell的heredoc功能。你只需要把你的字符串a
写入你刚启动的进程的标准输入管道就可以了。这其实和shell使用heredoc的方式是一样的。
你可以通过Popen.communicate()
来实现这一点:
p.communicate(a)
communicate()
函数的返回值包含了进程的输出(分为两个流,具体可以查看文档)。