【问题标题】:Getting command line arguments as tuples in python在python中将命令行参数作为元组获取
【发布时间】:2011-07-19 08:46:03
【问题描述】:

以下是我想如何调用脚本的示例:

python script.py -f file1.txt "string1" "string2" -f file2.txt "string3" "string4"

作为输入的每个文件都有 2 个与该文件关联的字符串。可以有任意数量的文件。

为简化起见,我试图得到这样的打印:

('file1.txt', 'string1', 'string2')
('file2.txt', 'string3', 'string4')

这是我目前所拥有的:

import sys, os, traceback, optparse
import time
import re
#from pexpect import run, spawn

def main ():
    global options, args

    print options.filename

    #for filename in options.filename:
    #  print filename
      #f = file(filename,'r')
      #for line in f:
      #  print line,
      #f.close()



if __name__ == '__main__':
    try:
        start_time = time.time()
        parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), usage=globals()['__doc__'], version='$Id$')
        parser.add_option ('-f', '--file', dest='filename', help='write report to FILE', metavar='FILE', nargs=3)
        parser.add_option ('-v', '--verbose', action='store_true', default=False, help='verbose output')
        (options, args) = parser.parse_args()
        #if len(args) < 1:
        #    parser.error ('missing argument')
        if options.verbose: print time.asctime()
        main()
        if options.verbose: print time.asctime()
        if options.verbose: print 'TOTAL TIME IN MINUTES:',
        if options.verbose: print (time.time() - start_time) / 60.0
        sys.exit(0)
    except KeyboardInterrupt, e: # Ctrl-C
        raise e
    except SystemExit, e: # sys.exit()
        raise e
    except Exception, e:
        print 'ERROR, UNEXPECTED EXCEPTION'
        print str(e)
        traceback.print_exc()
        os._exit(1)

使用上面的脚本,我只得到第二个文件和相关的字符串:

('file2.txt', 'string3', 'string4')

【问题讨论】:

  • 如果有人可以帮助我编写一些代码来实现我的目标(也许使用argparse),我将不胜感激。我尝试理解 argparse,但不知道如何进行。只有当我能够继续我的迷你项目时,我才会学习。现在我被困在参数解析阶段......开始赏金。

标签: python command-line-arguments optparse


【解决方案1】:

如果您使用optparse 是因为您希望与python 2.6 保持兼容,那么action='append' 解决方案也可以:

import optparse

parser = optparse.OptionParser()
parser.add_option('-f', '--file', dest='filename', nargs=3, action='append')

演示

>>> (opts, args)  = parser.parse_args("-f file1.txt string1 string2 -f file2.txt string3 string4".split())
>>> for fn_tuple in opts.filename:
...    print fn_tuple
('file1.txt', 'string1', 'string2')
('file2.txt', 'string3', 'string4')

【讨论】:

    【解决方案2】:

    我会以与上一个答案类似的方式处理这个问题,但会稍作调整:

    import getopt
    import sys
    
    args = sys.argv[1:]
    tuples = []
    while args:
    try:
        (opts, args) = getopt.getopt(args, "f:v", ["file=", "verbose"])
    except getopt.GetoptError, err:
        print str(err)
        sys.exit(2)    
    

    现在您可以通过以下方式要求输入:

    -f file1.txt,string1,string2
    

    并按如下方式解析:

    for opt, arg in opts:
        if opt in ("-f", "--file"):
            tuples.append(tuple(arg.split(",")))
        if opt in ("-v", "--verbose"):
            print "yep, verbose"
    print tuples
    

    或者将输入设计为一个字符串:

    -f "file1.txt string1 string2"
    

    然后根据你喜欢的东西分开。

    【讨论】:

      【解决方案3】:

      我认为您想使用add_argument 方法的action=append 参数

      import argparse
      
      parser= argparse.ArgumentParser()
      parser.add_argument ('-f', '--file', nargs=3, action='append')
      
      files = parser.parse_args('-f file1 string1 string2 -f file2 string3 string4 -f file3 string5 string6'.split()).file
      
      for f in files:
          print tuple(f)
      

      为您提供:

      ('file1', 'string1', 'string2')
      ('file2', 'string3', 'string4')
      ('file3', 'string5', 'string6')
      

      在 cli 上测试:

      与:

      import argparse
      
      parser= argparse.ArgumentParser(prog='Test', usage='%(prog)s -f Filename Option1 Option2 ')
      parser.add_argument ('-f', '--file', nargs=3, action='append')
      
      files = parser.parse_args().file
      
      for f in files:
          print tuple(f)
      

      结果:

      python test.py -f file1 "foo bar" "baz" -f file2 foo bar
      ('file1', 'foo bar', 'baz')
      ('file2', 'foo', 'bar')
      
      python test.py -f file1 "foo bar" "string2" -f file2 foo bar -f file3 "foo" "bar"
      ('file1', 'foo bar', 'string2')
      ('file2', 'foo', 'bar')
      ('file3', 'foo', 'bar')
      
      python test.py -f file1 "foo bar"
      usage: Test -f Filename Option1 Option2
      Test: error: argument -f/--file: expected 3 argument(s)
      

      【讨论】:

      • 这也适用于 optparse,因此您只需将 action='append' 添加到 parser.add_option
      • & @Emilio - 这在 optparse 上效果很好。非常感谢。接受此回复。
      【解决方案4】:

      您不是很清楚您的限制条件,但这适用于任意数量的 -fs 和其他标志

      import getopt
      import sys
      
      args = sys.argv[1:]
      tuples = []
      while args:
          try:
              opts, args = getopt.getopt(args, "f:v", ["file", "verbose"])
          except getopt.GetoptError, err:
              print str(err)
              sys.exit(-1)    
      
          for o, a in opts:
              if o in ("-f", "--file"):
                  tuples.append((a, args.pop(0), args.pop(0)))
              if o in ("-v", "--verbose"):
                  print "yep, verbose"
      
      print tuples
      

      【讨论】:

      • 刚刚做了一个测试...这会挂在不正确的输入上,例如-f file1.txt "string1" "string2" -f file2.txt "string3" --verbose "string4"
      【解决方案5】:

      argparse 支持累加器的概念,它允许您多次指定相同的选项,这可能更像您想要的,而不是 optparse 支持的任何东西(您的特殊问题是 optparse 没有知道如何处理多次指定的参数,所以它在命令行中是“最后一个获胜”)。 argparse 包含在 Python 2.7 和 3.2 中,但对于 2.6.x 或更高版本,您应该可以使用 download it

      【讨论】:

        猜你喜欢
        • 2016-02-07
        • 2020-07-11
        • 1970-01-01
        • 2019-08-08
        • 2016-02-17
        • 1970-01-01
        • 2011-08-10
        • 2011-11-15
        • 1970-01-01
        相关资源
        最近更新 更多