【问题标题】:python argparse: unrecognized argumentspython argparse:无法识别的参数
【发布时间】:2013-06-11 17:21:43
【问题描述】:

当我运行parsePlotSens.py -s bw hehe 时,它说hehe 是一个无法识别的参数。但是,如果我运行parsePlotSens.py hehe -s bw,就可以了。理想情况下,我希望它适用于这两种情况。

有什么建议吗?以下是我的代码:

if __name__ == '__main__' :

    parser = argparse.ArgumentParser(prog='parsePlotSens');
    parser.add_argument('-s', '--sort', nargs =1, action = 'store', choices = ['mcs', 'bw'], default='mcs', help=sorthelp)
    parser.add_argument('filename', nargs ='+', action = 'store')
    option = parser.parse_args(sys.argv)

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    不要将sys.argv 作为参数传递给parse_args。只需使用

    option = parser.parse_args()
    

    如果您确实将sys.argv 传递给parse_args,则脚本本身的路径或名称是sys.argv 中的第一项,因此成为option.filename 的值。 hehe 然后成为一个未知参数。

    如果您省略sys.argv,则parse_args 会按预期解析sys.argv

    【讨论】:

    • 您也可以调用 parser.parse_args(sys.argv[1:])。在内部 argparse 就是这样做的。
    • @MarioVilas 现在为什么你要重新实现你正在使用的库处理的东西?没有理由选择此选项而不是完全省略 sys.argv
    • @aidandeno MarioVilas 评论对于想要调用他们编写的函数的人可能很有用,该函数调用argparse.ArgumentParser 并从其参数中获取argparse.ArgumentParser 的参数。例如,也许有人想知道如何调用theirArgumentHandlerFunction 而不会得到“无法识别的参数”——就像theirArgumentHandlerFunction(sys.argv[1:]) 所建议的那样称呼它,就像马里奥维拉斯评论所建议的那样。
    • @MarioVilas 在编写单元测试时,最好将argv 传递给函数,而不是覆盖sys.argv 的值。
    【解决方案2】:

    你可以通过允许未知参数来解决这个问题

    替换

    args = parser.parse_args()
    

    args, unknown = parser.parse_known_args()
    

    【讨论】:

    • 这是最简单方便的解决方案。
    【解决方案3】:

    此外,作为对 unutbu 答案的补充,以这种方式将参数存储在字典中使测试变得容易:

    args = vars(parser.parse_args())
    print args
    

    打印字典:

    {'sort': ['bw'], 'filename': ['hehe']}
    

    喜欢:

    if args['sort'] == 'bw':
        # code here
    
    ...
    

    【讨论】:

    • 那是 always False 因为字符串 'bw'永远 等于其中包含该字符串的列表。我看不到在这里使用vars() 的原因。如果你忽略那个无意义的转换,测试就变成if args.sort == 'bw':。这就是它应该被使用的方式。
    【解决方案4】:

    我的情况与问题不一样,但错误是一样的。

    我的情况:

    1. 我有一个带有 windows pycharm 的远程开发 (SFTP),并上传以在 linux 上运行。
    2. python 命令在我的 bash 文件中有一些带有 \ 的换行符,比如

      python args_config.py \
          --arg1="hello" \
          --arg2="world"
      

    并引发python argparse: unrecognized arguments args not found 错误。

    问题是 bash 文件换行在 windows 和 linux 中不同,

    只是用pycharm设置File -> Line Separators -> LF - Unix and OS X (\n)

    上传到linux并运行bash文件,就可以了!

    【讨论】:

      【解决方案5】:

      为了完成这个answer,我在这里提供了一个获取和解析未知参数的示例:

      
      import argparse
      
      parser = argparse.ArgumentParser()
      # we only have a know argument  as key-pair --known KNOWN
      parser.add_argument('--known')
      
      # test with known un unknown variables
      args, unknown = parser.parse_known_args(["--known", "var", "--unknown", "bar", "--flag"])
      

      unknown 返回一个类似["--unknown", "bar", "--flag"] 的列表。我们只需要解析它:

      keypairs = dict([unknown[i:i+2] for i in range(0, len(unknown), 1) if unknown[i].startswith("--") and not (unknown[i+1:i+2]+["--"])[0].startswith("--")])
      
      flags = [unknown[i] for i in range(0, len(unknown), 2) if (unknown[i+1:i+2]+["--"])[0].startswith("--")]
      

      【讨论】:

        【解决方案6】:

        非常有用的线程。我和@Yan Zhu、@unutbu 和@FacePalm 的问题几乎相同,但我也需要接受 argv。我想出了这个,很好,因为它允许我编写不需要 sys.argv 参数的单元测试。

        import argparse, sys
        
        
        def parse(arg_list):
             p = argparse.ArgumentParser(description="my simple app")
             p.add_argument('-z', '--zeta', type=str, default='[zeta from default]')
             p.add_argument('-a', '--application', type=str, default='[application from default]')
             return p.parse_known_args(arg_list)
        
        
        code_args = [ '-a', 'a from code', '-q', 'q from code', '-o', 'o from code']
        
        print(parse(code_args + sys.argv[1:]))
        

        当您像这样-a 'a from intellij' 从 intellij 添加运行时参数时,结果如下所示。

        /usr/local/bin/python3.7 /Users/me/IdeaProjects/co-util-py/test/varargstest.py -a "a from intellij"
        
        (Namespace(application='a from intellij', other='o from code'), ['-q', 'q from code'])
        

        您可以看到 argparse 不会删除 q,但它也不会解析它。

        另外,经过大量的大脑疲劳和测试,sys.argv 和创建的列表之间唯一真正的区别是sys.argv[0] 是正在调用的程序的名称。从列表中删除它并不重要。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-14
          • 2012-09-30
          • 2015-07-20
          • 2021-08-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多