【问题标题】:Pipe output from shell command to a python script将 shell 命令的输出通过管道传输到 python 脚本
【发布时间】:2012-06-19 21:39:06
【问题描述】:

我想运行 mysql 命令并将其输出设置为我的 python 脚本中的变量。

这是我尝试运行的 shell 命令:

$ mysql my_database --html -e "select * from limbs" | ./script.py

这是python脚本:

#!/usr/bin/env python

import sys

def hello(variable):
    print variable

如何接受 python 脚本中的变量并让它打印输出?

【问题讨论】:

    标签: python unix


    【解决方案1】:

    您需要从标准输入读取数据以检索 python 脚本中的数据,例如

    #!/usr/bin/env python
    
    import sys
    
    def hello(variable):
        print variable
    
    data = sys.stdin.read()
    hello(data)
    

    如果您只想从 mysql 数据库中获取一些数据,然后使用 Python 对其进行操作,我会跳过将其通过管道传输到脚本中,而只需使用 the Python MySql module 进行 SQL 查询。

    【讨论】:

      【解决方案2】:

      如果您希望您的脚本表现得像许多 unix 命令行工具并接受管道或文件名作为第一个参数,您可以使用以下内容:

      #!/usr/bin/env python
      import sys
      
      # use stdin if it's full                                                        
      if not sys.stdin.isatty():
          input_stream = sys.stdin
      
      # otherwise, read the given filename                                            
      else:
          try:
              input_filename = sys.argv[1]
          except IndexError:
              message = 'need filename as first argument if stdin is not full'
              raise IndexError(message)
          else:
              input_stream = open(input_filename, 'rU')
      
      for line in input_stream:
          print(line) # do something useful with each line
      

      【讨论】:

        【解决方案3】:

        当您将一个命令的输出通过管道传输到 pytho 脚本时,它会转到 sys.stdin。您可以像读取文件一样读取 sys.stdin。示例:

        import sys
        
        print sys.stdin.read()
        

        这个程序按字面意思输出它的输入。

        【讨论】:

        • +1 用于提及“就像一个文件”,这有望让 OP 意识到他也可以做​​诸如“for line in sys.stdin:”之类的事情。
        【解决方案4】:

        由于在搜索 piping data to a python script 时会在 Google 顶部弹出此答案,因此我想添加另一种方法,在搜索比使用 @987654324 更“坚韧不拔”的方法后,我在 J. Beazley's Python Cookbook 中找到了该方法@。 IMO,即使对新用户来说也更加pythonic和不言自明。

        import fileinput
        with fileinput.input() as f_input:
            for line in f_input:
                print(line, end='')
        

        这种方法也适用于如下结构的命令:

        $ ls | ./filein.py          # Prints a directory listing to stdout.
        $ ./filein.py /etc/passwd   # Reads /etc/passwd to stdout.
        $ ./filein.py < /etc/passwd # Reads /etc/passwd to stdout.
        

        如果需要更复杂的解决方案,可以编译argparsefileinputas shown in this gist by martinth

        import argpase
        import fileinput
        
        if __name__ == '__main__':
            parser = ArgumentParser()
            parser.add_argument('--dummy', help='dummy argument')
            parser.add_argument('files', metavar='FILE', nargs='*', help='files to read, if empty, stdin is used')
            args = parser.parse_args()
        
            # If you would call fileinput.input() without files it would try to process all arguments.
            # We pass '-' as only file when argparse got no files which will cause fileinput to read from stdin
            for line in fileinput.input(files=args.files if len(args.files) > 0 else ('-', )):
                print(line)
        

        ```

        【讨论】:

        • 使用此方法出错(使用 python 2.7) Traceback(最近一次调用最后):文件“./pipetome.py”,第 4 行,在 中,fileinput.input() 为f_input: AttributeError: FileInput 实例没有属性'exit'
        • 以上内容仅在 Python3 中进行了测试——也许不是 with 尝试 f_input = fileinput.input() ?
        • 但是如何区分 args 和 stdin,例如 send_mail -to xxx@xxx.com -subject 'passwd' /passwd
        • 我已经用一个解决你所说的问题的例子更新了答案。
        【解决方案5】:

        可以使用命令行工具xargs

        echo 'arg1' | xargs python script.py

        arg1 现在可以从sys.argv[1] 中的script.py 访问

        【讨论】:

        • 这似乎不适用于多行管道内容。
        • @ZephaniahGrunschlag 我认为这与提供额外的 CLI 参数相同,例如:python script.py "gday"。没有xargs 依赖的单行代码会很好。
        • 我认为我的回答断章取义,所以我删除了它
        【解决方案6】:

        我偶然发现了这个尝试将 bash 命令传递给我没有编写的 python 脚本(并且不想修改以接受sys.stdin)。我发现这里提到的进程替换 (https://superuser.com/questions/461946/can-i-use-pipe-output-as-a-shell-script-argument) 可以正常工作。

        例如。 some_script.py -arg1 &lt;(bash command)

        【讨论】:

          【解决方案7】:

          同样适用于 WindowsPython 3.10.3one-liner 正在使用 sys.stdin.read(),如下所示:

          echo 'Hello!' | python -c "import sys;d=sys.stdin.read(); print('{}\n'.format(d))"
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-01-15
            • 2018-08-18
            • 2018-05-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多