【问题标题】:How can I take a variable number of files as input for a python script?如何将可变数量的文件作为 python 脚本的输入?
【发布时间】:2014-08-11 11:27:10
【问题描述】:

例如,我希望能够运行这个假设的命令:

$ python script.py *.txt option1 option2

并让它在每个匹配 *.txt 的文件上执行

目前我只找到一次操作一个文件的信息

from sys import argv

self, file, option1, option2 = argv

perform_operation(file, option1, option2)

#function definition

【问题讨论】:

  • 如果您可以一次打开一个文件,并且可以编写一个循环...那么您可以打开多个文件:-)。正如@sharth 所示,argv 是一个列表,argv[0] 是程序名称,argv[1:] 是其余参数。

标签: python shell python-2.7 command-line command-line-arguments


【解决方案1】:

你想使用 argparse-module:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("--option1")
parser.add_argument("--option2")
parser.add_argument("files", nargs="+")

opts = parser.parse_args()

print opts.option1
print opts.option2
print opts.files

这样使用:

 beer:~ deets$ python2.7 /tmp/argparse-test.py  text foo bar baz
 None
 None
 ['text', 'foo', 'bar', 'baz']

【讨论】:

    【解决方案2】:

    argv 是一个列表。假设您只传递文件名参数。如果它更复杂,那么请使用 deets 的答案。

    self = sys.argv[0]
    arguments = sys.argv[1:]
    

    现在,arguments 是程序参数列表。假设我们要一次处理一个:

    for argument in arguments:
        work(argument)
    

    或者我们想将它们全部传递给一个函数:

    work(arguments)
    

    关于将*.txt 作为参数传递。您的 shell(甚至在您的程序运行之前)将为您完成大部分工作。

    如果我运行python program.py *.txt,其中*.txt 指的是3 个文本文件,那么我的shell 将扩展它,这样我的程序就会看到python program.py a.txt b.txt c.txt

    【讨论】:

    • 我接受可变数量的文件名,然后是另外两个参数。我正在编写的脚本应该遍历每个文件并将与第一个参数匹配的任何文本替换为第二个参数。您在上面提供的解决方案对我有用,因为在这种情况下我总是可以假设最后两个参数不是文件名。谢谢!
    • 如果您确定它们总是最后两个参数,那么您可以通过执行以下操作获取文件名:sys.argv[1:][:-2]。但是,一旦您开始添加命令行参数,我强烈建议您使用 ArgumentParser,如 deets 的回答所示。
    • 这可以缩短为 sys.argv[1:-2],这就是我为这个脚本采用的解决方案。如果我遇到更复杂的事情,我会选择 deet 的答案。
    【解决方案3】:

    multifile.py

    """
    Usage:
        multifile.py <file>...
        multifile.py -h
    
    Prints something about all the <file>... files.
    """
    
    def main(files):
        for fname in files:
            print fname
    
    if __name__ == "__main__":
        from docopt import docopt
        args = docopt(__doc__)
        files = args["<file>"]
        main(files)
    

    使用它

    先安装docopt

    $ pip install docopt
    

    调用不带参数的命令:

    $ python multifile.py
    Usage:
        multifile.py <file>...
        multifile.py -h
    

    尝试帮助

    $ python multifile.py -h
    Usage:
        multifile.py <file>...
        multifile.py -h
    
    Prints something about all the <file>... files.
    

    将其用于一个文件:

    $ python multifile.py alfa.py 
    alfa.py
    

    将它用于多个文件,使用通配符:

    $ python multifile.py ../*.py
    
        ../camera2xml.py
        ../cgi.py
        ../classs.py
    

    结论

    • docopt 允许更多选项(请参阅docopt
    • 命令行解析在Python中很容易
      • argparse 似乎是 Python 2.7 版以来的标准部分
      • argparse 可以做很多事情,但需要在很多行上进行相当复杂的调用
      • plac 是不错的选择,在大多数情况下可以快速服务器
      • docopt 在我看来是最灵活的,同时所需的代码行数也是最短的

    【讨论】:

      【解决方案4】:

      使用标准库中的inputfile

      stdlib 中有一个经常被忽视的库,叫做inputfile

      默认情况下,它会将命令行或标准输入的所有输入作为文件名处理,并且不仅允许迭代这些文件,还允许迭代其中的所有行、修改它们、解压缩和许多其他实际操作。

      filenames.py - 列出所有文件名

      import fileinput
      
      for line in fileinput.input():
          print "File name is: ", fileinput.filename()
          fileinput.nextfile()
      

      叫它:

      $ python filenames.py *.txt
      File name is: films.txt
      File name is: highscores.txt
      File name is: Logging.txt
      File name is: outtext.txt
      File name is: text.txt
      

      upperlines.py - 以大写形式打印多个文件中的所有行

      import fileinput
      
      for line in fileinput.input():
          print line.upper(),
      

      然后调用它:

      $ python upperlines.py *.txt
      THE SHAWSHANK REDEMPTION (1994)
      THE GODFATHER (1972)
      THE GODFATHER: PART II (1974)
      THE DARK KNIGHT (2008)
      PULP FICTION (1994)
      JAN HAS SCORE OF 101
      PIETER HAS SCORE OF 900
      CYRIL HAS SCORE OF 2
      2014 APR 11  07:14:03.155  SECTORBLAH
         INTERESTINGCONTENT
         INTERESTING1 = 843
      1. LUV_DEV <- HE'S A DEVELOPER
      2. AMIT_DEV <- HE'S A DEVELOPER
      ....
      

      upperlinesinplace.py - 将文件中的所有行转为大写

      import fileinput
      
      for line in fileinput.input(inplace=True):
          print line.upper(),
      

      结论

      • fileinput 采用默认参数 sys.argv[:1] 并遍历所有文件和行
      • 您可以传递自己的文件名列表进行处理
      • fileinput 允许就地更改、过滤、读取文件名、行号...
      • fileinput 甚至允许处理压缩文件

      【讨论】:

        猜你喜欢
        • 2015-07-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-11
        • 1970-01-01
        • 2017-04-21
        • 1970-01-01
        • 2023-01-11
        • 2014-09-02
        相关资源
        最近更新 更多