【问题标题】:Python subprocess with heredocs带有 heredocs 的 Python 子进程
【发布时间】:2010-11-25 10:48:09
【问题描述】:

我在玩 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 程序中执行,因为有更好的方法来执行此操作。

【问题讨论】:

    标签: python subprocess heredoc


    【解决方案1】:

    从 Python 3.5 开始,您可以使用 subrocess.run,如下所示:

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

    【讨论】:

      【解决方案2】:

      您将 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)
      

      【讨论】:

      • 这是一个有用的答案。如果你能给出如何以 Pythonic 方式执行此操作的代码建议,那就更好了。
      • 正如我在问题中所说,这只是在玩子进程,我永远不会做类似在 Python 中调用 cat 的事情。出于好奇,更多的是用于实际代码。
      • "你应该使用 Python 特性而不是在你的 Python 脚本中调用 shell 脚本。"并非所有 shell 功能都在 Python 中可用。一个heredoc可以被提供给许多不同类型的没有Python接口的程序,并且可以用Python动态生成heredoc的内容。
      • @user5359531,我为此添加了一个简单的示例。
      【解决方案3】:

      外壳“heredoc”支持是外壳功能。 subprocess.Popen 默认不通过 shell 运行你的命令,所以这个语法肯定行不通。

      但是,由于无论如何您都在使用管道,因此无需使用 shell 的 heredoc 支持。只需将您的字符串a 写入您刚刚启动的进程的标准输入管道。无论如何,这正是 shell 对 heredoc 所做的事情。

      您可以使用Popen.communicate()

      p.communicate(a)
      

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

      【讨论】:

      • 我不太明白 Shell 参数的作用。文档很好地解释了当你将它设置为 true 时会发生什么,但当它设置为 false 时却没有那么多。
      • shell 参数为False 时,subprocess 模块会直接执行您指定的程序(在您的情况下,可能是/bin/cat),并使用对@ 的调用中指定的参数987654331@。没有解释诸如重定向或管道之类的 shell 字符或任何事情,程序会准确地看到您发送的内容。这就是为什么cat 说找不到以&lt;&lt;DATA 开头的文件。
      • 感谢您的解释,澄清了几件事。
      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2015-04-16
        • 2020-05-12
        • 2021-12-02
        • 2017-07-27
        • 2015-01-03
        • 2019-12-01
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多