【问题标题】:Multiple arguments with stdin in PythonPython中标准输入的多个参数
【发布时间】:2013-09-12 06:27:00
【问题描述】:

我有一个棘手的问题,涉及从 Unix 终端运行 Python 脚本时传递多个标准输入参数。 考虑以下命令:

$ cat file.txt | python3.1 pythonfile.py

然后file.txt的内容(通过“cat”命令访问)将作为标准输入传递给python脚本。这很好(虽然更优雅的方式会很好)。但是现在我必须传递另一个参数,它只是一个将用作查询的单词(以及后面的两个单词)。但我不知道如何正确地做到这一点,因为 cat 管道会产生错误。而且你不能在 Python 中使用标准的 input(),因为它会导致 EOF 错误(你不能在 Python 中组合 stdin 和 input()

【问题讨论】:

  • 如果你想要优雅,请跳过catpython3.1 pythonfile.py <file.txt

标签: python pipe stdin eof variadic-functions


【解决方案1】:

我有理由相信标准输入标记可以解决问题:

cat file.txt | python3.1 prearg - postarg

更优雅的方法可能是将 file.txt 作为参数传递,然后打开并读取它。

【讨论】:

    【解决方案2】:

    argparse 模块会给你很多更多的灵活性来使用命令行参数。

    import argparse
    
    parser = argparse.ArgumentParser(prog='uppercase')
    parser.add_argument('-f','--filename',
                        help='Any text file will do.')                # filename arg
    parser.add_argument('-u','--uppercase', action='store_true',
                        help='If set, all letters become uppercase.') # boolean arg
    args = parser.parse_args()
    if args.filename:                       # if a filename is supplied...
        print 'reading file...'
        f = open(args.filename).read()
        if args.uppercase:                  # and if boolean argument is given...
            print f.upper()                 # do your thing
        else:
            print f                         # or do nothing
    
    else:
        parser.print_help()                 # or print help
    

    所以当你不带参数运行时,你会得到:

    /home/myuser$ python test.py
    usage: uppercase [-h] [-f FILENAME] [-u]
    
    optional arguments:
      -h, --help            show this help message and exit
      -f FILENAME, --filename FILENAME
                            Any text file will do.
      -u, --uppercase       If set, all letters become uppercase.
    

    【讨论】:

      【解决方案3】:

      假设绝对需要将内容作为标准输入而不是文件路径传递,因为您的脚本位于 docker 容器或其他东西中,但是您还有其他需要传递的参数......所以做类似的事情这个

      import sys
      import argparse
      
      if __name__ == '__main__':
          parser = argparse.ArgumentParser()
          parser.add_argument('-dothis', '--DoThis', help='True or False', required=True)
          # add as many such arguments as u want
      
          args = vars(parser.parse_args())
      
          if args['DoThis']=="True":
              content = ""
              for line in sys.stdin:
                  content = content + line
              print "stdin - " + content
      

      要运行此脚本,请执行此操作

      $ cat abc.txt | script.py -dothis 真

      $ echo "你好" | script.py -dothis 真

      变量内容将存储在管道左侧打印出来的任何内容,“|”,您还可以提供脚本参数。

      【讨论】:

      • 支持stdin 有更根本的原因,比如让您使用另一个进程作为输入而无需任何临时文件。这显着提高了效率,内核甚至免费为您限制上游进程的速率。
      【解决方案4】:

      虽然史蒂夫巴恩斯的回答会奏效,但它并不是真正最“pythonic”的做事方式。更优雅的方法是使用 sys 参数并在脚本本身中打开和读取文件。这样您就不必通过管道输出文件并找出解决方法,您只需将文件名作为另一个参数传递即可。

      类似于(在 python 脚本中):

      import sys
      
      with open(sys.argv[1].strip) as f:
          file_contents = f.readlines()
          # Do basic transformations on file contents here
          transformed_file_contents = format(file_contents)
      
      # Do the rest of your actions outside the with block, 
      # this will allow the file to close and is the idiomatic 
      # way to do this in python
      

      所以(在命令行中):

      python3.1 pythonfile.py file.txt postarg1 postarg2
      

      【讨论】:

      • 谢谢!我也想到了这个方法。传递文件名可能是一种更优雅的解决方案,可以将所有数据保存在 Python 中,而不是从外部提供。标记为已解决!
      • 我不认为使用标准输入有什么非 pythonic 的。在某些情况下 - 例如您希望输入从另一个进程流式传输 - stdin 更合适。
      • @joeln 我同意这并不是真正的固有 unpythonic,只是在这种情况下,我认为将逻辑保留在脚本中会更干净。
      • 另外作者要求一种比标准输入“更优雅”的方式来传递文件。
      猜你喜欢
      • 1970-01-01
      • 2012-01-19
      • 1970-01-01
      • 2014-08-02
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多