使用heredocs的Python子进程

时间:2009-09-03 21:17:30

标签: python subprocess heredoc

我正在使用Python的子进程模块,尝试一些示例,但我似乎无法使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 个答案:

答案 0 :(得分:4)

shell“heredoc”支持是一个shell功能。 <{1}}默认情况下不会通过shell运行命令,因此这种语法肯定不起作用。

但是,由于您无论如何都在使用管道,因此无需使用shell的heredoc支持。只需将字符串subprocess.Popen写入刚刚启动的进程的stdin管道。无论如何,这正是shell对heredoc的作用。

您可以使用Popen.communicate()执行此操作:

a

p.communicate(a) 函数的返回值包含进程的输出(在两个流中,请参阅文档)。

答案 1 :(得分:4)

正如其他人所指出的,你需要在shell中运行它。 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

答案 2 :(得分:3)

您将shell语法作为cat程序的参数传递。您可以尝试这样做:

p = subprocess.Popen(["sh", "-c", "cat <<DATA\n" + a + "\nDATA"])

但这个概念本身是错误的。您应该使用Python功能,而不是在python脚本中调用shell脚本。

在这种特殊情况下,你应该使用shell的heredoc语法插入变量,因此你需要转义a中的所有文本,并确保其中没有DATA行。


对于Python等价物,我认为最接近这个(假设你不想只是print(a) ;-))是将变量的值传递给生成过程的stdin:

p = subprocess.Popen(["program", ...], stdin=subprocess.PIPE)
p.communicate(a)

答案 3 :(得分:0)

从 Python 3.5 开始,您可以像这样使用 subrocess.run

subprocess.run(['cat'], input=b"A String of Text")