【问题标题】:How do I pipe output from one python script as input to another python script?如何将一个 python 脚本的输出作为输入传递给另一个 python 脚本?
【发布时间】:2016-06-15 23:02:00
【问题描述】:

例如:

script1.py 从用户处获取中缀表达式并将其转换为后缀表达式并返回或打印到标准输出

script2.py 从标准输入获取一个后缀表达式并对其求值并输出值

我想做这样的事情:

python3 script1.py | python3 script2.py

但这不起作用,你能指出我如何做到这一点的正确方向吗?

编辑-

这里有一些关于“不起作用”的更多细节。

当我执行 python3 script1.py | python3 script2.py 终端要求我输入 script2.py 程序,而它应该要求输入 script1.py 程序并将其重定向为 script2.py 的输入。

所以它要求我“输入一个后缀表达式:”,当它应该问“输入一个中缀表达式:”并将其重定向到后缀脚本时。

【问题讨论】:

  • 如果将它们作为函数并按顺序调用它们会有什么问题。顺便说一句,您的方式应该可行,问题一定是您的反序列化。
  • 该命令行应该完全按照您所说的去做。 准确地说,它如何未能满足您的期望? (“它不起作用”是一个完全没有信息的问题报告。)
  • 我将脚本定义为两个单独的函数并按顺序调用它们并没有错,但我想学习如何以这种方式进行操作。至于反序列化,你能详细说明一下吗?
  • @rici 我提供了有关该问题的更多详细信息,希望对您有所帮助。
  • @7alman:想想发生了什么。您正在将第一个脚本的输出重定向到第二个脚本。所以如果你的第一个脚本输出“输入一个中缀表达式”,你认为输出会去哪里??? (当输入来自另一个脚本而不是人类时,第二个脚本提示是多么愚蠢?)这就是脚本不应该提示的原因。如果您坚持提示,则应将提示发送到stderr,而不是stdout。

标签: bash shell python-3.x pipe io-redirection


【解决方案1】:

如果我正确地理解了您的问题,您的两个脚本会分别写出一个输入提示。例如,它们都可能是这样的:

in_string = input("Enter something")
print(some_function(in_string))

其中some_function 是一个函数,其输出取决于输入字符串(在每个脚本中可能不同)。

问题是当一个脚本的输出被传送到另一个脚本时,"Enter something" 提示没有正确显示给用户。那是因为提示被写入标准输出,所以第一个脚本的提示通过管道传送到第二个脚本,同时显示第二个脚本的提示。这是一种误导,因为它是第一个(直接)接收用户输入的脚本。提示文本也可能会混淆两个脚本之间传递的数据。

这个问题没有完美的解决方案。一种部分解决方案是将提示写入标准错误,而不是标准输出。这会让您看到两个提示(尽管您实际上只能响应其中一个)。我不认为你可以直接用input 做到这一点,但print 可以根据需要写入其他文件流:print("prompt", file=sys.stderr)

另一个部分解决方案是检查您的输入和输出流是否存在,如果其中一个不是“tty”(终端),则跳过打印提示。在 Python 中,您可以使用sys.stdin.isatty()。如果许多命令行程序直接连接到用户,而不是连接到管道或文件,则它们具有不同的“交互模式”。

如果管道输出是您程序的主要功能,您可能永远不想使用提示!许多标准的 Unix 命令行程序(如 catgrep)根本没有任何交互行为。它们要求用户传递命令行参数或设置环境变量来控制它们的运行方式。即使他们无法访问标准输入和标准输出,这也可以让他们按预期工作。

【讨论】:

    【解决方案2】:

    例如,如果您正在运行 nginx 和 script1.py:

    import os
    
    os.system("ps aux")
    

    和 script2.py

    import os
    
    os.system("grep nginx")
    

    然后运行:

    python script1.py | script2.py
    

    将与

    相同
    ps aux | grep nginx
    

    【讨论】:

      【解决方案3】:

      为了完成,并提供使用 os 模块的替代方法:

      fileinput 模块会为您处理管道,通过运行一个简单的测试,我相信它会使其成为一个简单的实现。

      要使您的文件支持管道输入,只需执行以下操作:

      import fileinput
      with fileinput.input() as f_input:  # This gets the piped data for you
          for line in f_input:
              # do stuff with line of piped data
      

      你所要做的就是:

      $ some_textfile.txt | ./myscript.py
      

      请注意,fileinput 还可以为您的脚本启用数据输入,如下所示: $ ./myscript.py some_textfile.txt $ ./myscript.py

      这同样适用于 python 的打印输出:

      >test.py  # This prints the contents of some_textfile.txt
      with open('some_textfile.txt', 'r') as f:
          for line in f:
              print(line)
      
      $ ./test.py | ./myscript.py
      

      当然,不要忘记脚本顶部的 hashbang #!/usr/bin/env python 以使这种方式起作用。

      该食谱在Beazley & Jones's Python Cookbook 中有特色 - 我全心全意地推荐它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-13
        • 2018-02-04
        • 1970-01-01
        • 2022-12-08
        相关资源
        最近更新 更多