【问题标题】:How to read/process command line arguments?如何读取/处理命令行参数?
【发布时间】:2023-03-30 07:03:02
【问题描述】:

【问题讨论】:

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


【解决方案1】:

标准库中的规范解决方案是argparsedocs):

这是一个例子:

from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument("-f", "--file", dest="filename",
                    help="write report to FILE", metavar="FILE")
parser.add_argument("-q", "--quiet",
                    action="store_false", dest="verbose", default=True,
                    help="don't print status messages to stdout")

args = parser.parse_args()

argparse 支持(除其他外):

  • 任意顺序的多个选项。
  • 短选项和长选项。
  • 默认值。
  • 生成使用帮助消息。

【讨论】:

  • 是的,这些是最好的。由于它们是标准库的一部分,因此您可以确保它们可用并且易于使用。 optparse 尤其强大且简单。
  • optparse 是最好的之一; getopt 已经过时了,确实应该被弃用。
  • 此时 (12/2011),argparse 现在被认为是比 optparse 更好的选择,对吗?
  • Python 文档建议使用 argparse 而不是 optparse。
  • 由于 optparse 已被弃用,问题的提问者不再是堆栈溢出的成员,这是一个高度可见的问题的公认答案 - 请考虑完全重写您的示例代码以使用改为 stdlib argparse
【解决方案2】:
import sys

print("\n".join(sys.argv))

sys.argv 是一个列表,其中包含在命令行上传递给脚本的所有参数。 sys.argv[0] 是脚本名称。

基本上,

import sys
print(sys.argv[1:])

【讨论】:

  • 对于非常简单的东西,这是要走的路,尽管您可能只想使用sys.argv[1:](避免使用脚本名称)。
【解决方案3】:

一种方法是使用sys.argv。这将打印脚本名称作为第一个参数以及您传递给它的所有其他参数。

import sys

for arg in sys.argv:
    print arg

【讨论】:

    【解决方案4】:

    我喜欢 stdlib 中的 getopt,例如:

    try:
        opts, args = getopt.getopt(sys.argv[1:], 'h', ['help'])
    except getopt.GetoptError, err: 
        usage(err)
    
    for opt, arg in opts:
        if opt in ('-h', '--help'): 
            usage()
    
    if len(args) != 1:
        usage("specify thing...")
    

    最近我一直在包装与此类似的东西以减少冗长(例如;使“-h”隐含)。

    【讨论】:

      【解决方案5】:

      还有argparse stdlib module(stdlib 的optparse 模块上的“改进”)。来自the introduction to argparse的示例:

      # script.py
      import argparse
      
      if __name__ == '__main__':
          parser = argparse.ArgumentParser()
          parser.add_argument(
              'integers', metavar='int', type=int, choices=range(10),
               nargs='+', help='an integer in the range 0..9')
          parser.add_argument(
              '--sum', dest='accumulate', action='store_const', const=sum,
              default=max, help='sum the integers (default: find the max)')
      
          args = parser.parse_args()
          print(args.accumulate(args.integers))
      

      用法:

      $ script.py 1 2 3 4
      4
      
      $ script.py --sum 1 2 3 4
      10
      

      【讨论】:

      • 只是复制粘贴
      • @blitu12345 在发布我的答案时,没有其他答案以任何方式提及 argparse。模块本身不在标准库中¶你对文档中的代码示例有什么看法?为什么你认为有必要拿出你自己的例子而不是模块作者提供的例子?而且我不喜欢仅链接的答案(我并不孤单)。
      • 来到这里的人们已经知道文档中的内容,并且只是为了进一步了解该主题而来到这里。我的情况也是如此,但我在这里真正找到的是原始文档的复制和粘贴.和平!
      • “来到这里的人们已经知道文档中的内容” - 我高度怀疑这个假设。以某种方式。
      【解决方案6】:

      我自己使用 optparse,但非常喜欢 Simon Willison 最近推出的 optfunc 库所采用的方向。它的工作原理:

      "自省函数 定义(包括它的论点 及其默认值)并使用 构造一个命令行 参数解析器。”

      例如,这个函数定义:

      def geocode(s, api_key='', geocoder='google', list_geocoders=False):
      

      变成了这个 optparse 帮助文本:

          Options:
            -h, --help            show this help message and exit
            -l, --list-geocoders
            -a API_KEY, --api-key=API_KEY
            -g GEOCODER, --geocoder=GEOCODER
      

      【讨论】:

        【解决方案7】:

        只是为argparse 传福音,这对these 来说更好。.. 本质上:

        (从链接复制)

        • argparse 模块可以处理位置 和可选参数,而 optparse 只能处理可选的 论据

        • argparse 不是教条式的 你的命令行界面是什么 应该看起来像 - 像 -file 这样的选项 或 /file 支持,因为是 必需的选项。 Optparse 拒绝 支持这些功能,更喜欢 纯粹大于实用

        • argparse 产生更多 信息性使用消息,包括 命令行用法由 你的论点和帮助信息 位置和可选 论据。 optparse 模块 要求您编写自己的用法 字符串,无法显示 位置参数的帮助。

        • argparse 支持以下操作 消耗可变数量的 命令行参数,而 optparse 要求确切的数量 参数(例如 1、2 或 3)是已知的 提前

        • argparse 支持以下解析器 分派到子命令,而 optparse 需要设置 allow_interspersed_args 并做 解析器手动调度

        还有我个人最喜欢的:

        • argparse 允许类型和 动作参数到add_argument() 用简单的方式指定 可调用对象,而 optparse 需要 黑客类属性,如 STORE_ACTIONSCHECK_METHODS 获取 正确的参数检查

        【讨论】:

        • 这现在是标准 Python 2.7 和 3.2 的一部分 :)
        • 什么是“可选参数”?你说他们在 optparse 中。我认为它们是可能提供也可能不提供的参数,但您说它们在 optparse 中,同时继续说“optparse 要求提前知道参数的确切数量”。因此,要么您对“可选参数”的定义与我的想法不同,要么您的答案与自己不一致。
        • 只是一个抱怨:​​argparse 文档也非常复杂。对于“如何使命令行参数接受单个值,以及如何访问该值”,您无法得到简单的答案。
        • @osman 这个温柔的tutorial argparse 可能会有所帮助...
        • @ArtOfWarfare “可选参数”在此上下文中可能表示使用类似选项的参数指定的参数,例如 -f--foo,而“提前知道参数的确切数量”可能表示位置给出的参数没有任何前面的选项标志。
        【解决方案8】:

        您可能对我编写的一个 Python 小模块感兴趣,它可以让命令行参数的处理更加轻松(开源且免费使用)-Commando

        【讨论】:

        • 已经有另一个名为 Commando 的命令行解析模块:github.com/lakshmivyas/commando。它使用装饰器包装 argparse。
        • python 和轮子的再发明
        【解决方案9】:

        如您所见 optparse “optparse 模块已弃用,不会进一步开发;开发将继续使用 argparse 模块。”

        【讨论】:

          【解决方案10】:

          我的解决方案是entrypoint2。示例:

          from entrypoint2 import entrypoint
          @entrypoint
          def add(file, quiet=True): 
              ''' This function writes report.
          
              :param file: write report to FILE
              :param quiet: don't print status messages to stdout
              '''
              print file,quiet
          

          帮助文本:

          usage: report.py [-h] [-q] [--debug] file
          
          This function writes report.
          
          positional arguments:
            file         write report to FILE
          
          optional arguments:
            -h, --help   show this help message and exit
            -q, --quiet  don't print status messages to stdout
            --debug      set logging level to DEBUG
          

          【讨论】:

            【解决方案11】:
            #set default args as -h , if no args:
            if len(sys.argv) == 1: sys.argv[1:] = ["-h"]
            

            【讨论】:

              【解决方案12】:

              docopt 库非常漂亮。它根据您的应用程序的使用字符串构建一个参数 dict。

              例如来自 docopt 自述文件:

              """Naval Fate.
              
              Usage:
                naval_fate.py ship new <name>...
                naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
                naval_fate.py ship shoot <x> <y>
                naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
                naval_fate.py (-h | --help)
                naval_fate.py --version
              
              Options:
                -h --help     Show this screen.
                --version     Show version.
                --speed=<kn>  Speed in knots [default: 10].
                --moored      Moored (anchored) mine.
                --drifting    Drifting mine.
              
              """
              from docopt import docopt
              
              
              if __name__ == '__main__':
                  arguments = docopt(__doc__, version='Naval Fate 2.0')
                  print(arguments)
              

              【讨论】:

              • 这已迅速成为我最喜欢的方式。它是字符串解析,所以有点脆弱,但它很脆弱 all in one place,您可以在 try.docopt.org 预览您的逻辑。可选的和互斥的参数以一种非常优雅的方式完成。
              • 我迫切希望看到 naval_fate.py 的其余代码
              【解决方案13】:

              我建议将 docopt 作为其他这些的简单替代品。

              docopt 是一个新项目,它通过解析您的 --help 使用消息而不是要求您自己实现所有内容来工作。您只需将您的使用信息以 POSIX 格式输入即可。

              【讨论】:

                【解决方案14】:

                Pocoo 的 click 更直观,需要的样板更少,并且至少与 argparse 一样强大。

                到目前为止,我遇到的唯一弱点是您无法对帮助页面进行太多自定义,但这通常不是必需的,docopt 似乎是明确的选择。

                【讨论】:

                  【解决方案15】:

                  如果您需要快速且不太灵活的东西

                  ma​​in.py:

                  import sys
                  
                  first_name = sys.argv[1]
                  last_name = sys.argv[2]
                  print("Hello " + first_name + " " + last_name)
                  

                  然后运行python main.py James Smith

                  产生以下输出:

                  你好詹姆斯·史密斯

                  【讨论】:

                  • 更现实的用法是python main.py "James Smith",它将James Smith 放入sys.argv[1] 并在您尝试使用不存在的sys.argv[2] 时生成IndexError。引用行为在一定程度上取决于您从哪个平台和 shell 运行 Python。
                  • 我不同意我的用法不太现实。假设您的程序需要知道一个人的确切名字和姓氏才能在人们可以拥有多个名字和姓氏的企业中运行脚本?如果詹姆斯史密斯将约瑟夫作为额外的名字或姓氏,如果您只使用python main.py "James Joseph Smith",如何区分约瑟夫是额外的名字还是姓氏?如果您担心索引超出范围,可以添加对提供的参数数量的检查。不管是否不太现实,我的示例展示了如何处理多个参数。
                  • 所有其他答案都是为了策划登月任务。我只是简单地使用gmail-trash-msg.py MessageID。这个答案直截了当地测试MessageID 参数已在sys.argv[1] 中传递。
                  【解决方案16】:

                  另一个选项是argh。它建立在 argparse 之上,让您可以编写如下内容:

                  import argh
                  
                  # declaring:
                  
                  def echo(text):
                      "Returns given word as is."
                      return text
                  
                  def greet(name, greeting='Hello'):
                      "Greets the user with given name. The greeting is customizable."
                      return greeting + ', ' + name
                  
                  # assembling:
                  
                  parser = argh.ArghParser()
                  parser.add_commands([echo, greet])
                  
                  # dispatching:
                  
                  if __name__ == '__main__':
                      parser.dispatch()
                  

                  它将自动生成帮助等,您可以使用装饰器来提供有关 arg-parsing 应该如何工作的额外指导。

                  【讨论】:

                  • 这是最好的解决方案。使用argh 比使用其他库或使用sys 更容易。
                  • 我想点赞argh,但它并不特别适合您最希望没有带有子命令的命令的场景。
                  • @tripleee YMMV,但我发现这更多的是文档中的缺陷,而不是库本身。让def frobnicate_spleches(...) 定义一个函数来执行您的脚本所做的任何事情,然后在文件末尾执行if __name__ == '__main__': argh.dispatch_command(frobnicate_spleches) 似乎是完全可行的。
                  【解决方案17】:
                  import argparse
                  
                  parser = argparse.ArgumentParser(description='Process some integers.')
                  parser.add_argument('integers', metavar='N', type=int, nargs='+',
                                     help='an integer for the accumulator')
                  parser.add_argument('--sum', dest='accumulate', action='store_const',
                                     const=sum, default=max,
                                     help='sum the integers (default: find the max)')
                  
                  args = parser.parse_args()
                  print(args.accumulate(args.integers))
                  
                  Assuming the Python code above is saved into a file called prog.py
                  $ python prog.py -h
                  
                  Ref-link: https://docs.python.org/3.3/library/argparse.html
                  

                  【讨论】:

                    【解决方案18】:

                    在 python3 中,您可能会发现使用扩展的可迭代解包来处理可选的位置参数很方便,而无需额外的依赖:

                    try:
                       _, arg1, arg2, arg3, *_ = sys.argv + [None] * 2
                    except ValueError:
                       print("Not enough arguments", file=sys.stderr) # unhandled exception traceback is meaningful enough also
                       exit(-1)
                    

                    上面的argv解包使得arg2arg3“可选”——如果在argv中没有指定它们,它们将为None,而如果第一个没有指定,则会出现ValueError:

                    Traceback (most recent call last):
                      File "test.py", line 3, in <module>
                        _, arg1, arg2, arg3, *_ = sys.argv + [None] * 2
                    ValueError: not enough values to unpack (expected at least 4, got 3)
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-05-01
                      • 1970-01-01
                      • 2020-06-26
                      • 2013-05-08
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多