【问题标题】:optional nargs variable in argparseargparse 中的可选 nargs 变量
【发布时间】:2016-11-01 18:00:15
【问题描述】:

如何使用带有变量 nargs 的 argparse 进行条件循环?所以,基本上,它应该在有或没有参数的情况下运行。 我正在尝试:

parser = argparse.ArgumentParser(description="output parser")
group = parser.add_mutually_exclusive_group()
group.add_argument("--dos", help="get DOSCAR for plot",
                   nargs="?", metavar=("int"))
args = parser.parse_args()

if args.dos:    
    if len(args.dos) > 1:
        chosen = int(args.dos[0])
        chdos = "at_dos"+args.dos[0]+".dat"
    else:
        chosen = None

    inpt = "DOSY"
    print(chosen)
    print(inpt)

现在,如果我有变量,那么它会打印一些值,错误但有一些值:

$python3 vasp.py --dos 111
111
None   # IT SHOULDN'T BE NONE
DOSY

但没有争论。

我也尝试过使用普通的 sys.argv,如:

def get_dos():
    if len(sys.argv) > 2:
        chosen = int(sys.argv[2])
        chdos = "at_dos"+sys.argv[2]+".dat"
    else:
        chosen = None
    inpt = "DOSCAR"
    print(sys.argv)

    print(args.dos)
    print(chosen)
    print(inpt)

在这种情况下,当存在选项时,它给出正确的结果:

python3 vasp.py --dos 12
['vasp.py', '--dos', '12']
12
12
DOSCAR

但同样,没有选择:

$python3 vasp.py --dos

我已经尝试过 hpaulj 的建议。它给出了:

$python3 tt.py --dos 12
Namespace(dos='12')
1
DOSY

没有参数,它仍然没有打印任何东西。

【问题讨论】:

  • 当我运行它并修复无效语法时,我没有得到 None。你使用的是什么版本的 Python?我已经尝试过 3.5.1 和 2.7.11 并且在两个版本中都可以使用。你需要一个minimal reproducible example
  • 另外,我认为len(args.dos) > 1 不会像您认为的那样做。它会检查您是否输入了超过 1 位的数字。
  • 你试过print(args)直接看解析了什么吗?
  • 您现在需要一个可以处理字符串“12”的测试,而不是列表或数字。一个字符串。
  • 只使用--dos 而没有它应该做什么?

标签: python argparse


【解决方案1】:

在 Ipython 会话中简化您的解析器:

In [1004]: parser=argparse.ArgumentParser()    
In [1005]: parser.add_argument('--dos', nargs='?')

In [1007]: parser.parse_args('--dos 111'.split())
Out[1007]: Namespace(dos='111')

在这种情况下,args.dos 将是字符串“111”,len 为 3,int(args.dos[0]) 为数字 1。同样的情况发生在您将 nargs 留空(默认为无)。

对于nargs='?',我也可以使用不带参数的标志,在这种情况下,值是默认的None

In [1013]: parser.parse_args('--dos'.split())
Out[1013]: Namespace(dos=None)

nargs=?is most useful with aconst, which gives a convenient 3 way action. I can addtype=int` 将字符串(如果有)转换为整数。

In [1015]: parser.add_argument('--dos', nargs='?', type=int,
   default=None, const=123)

In [1016]: parser.parse_args([]) # not used
Out[1016]: Namespace(dos=None)

In [1017]: parser.parse_args('--dos'.split())  # without argument
Out[1017]: Namespace(dos=123)

In [1018]: parser.parse_args('--dos 456'.split())  # with argument
Out[1018]: Namespace(dos=456)

其他nargs,如 1、'*' 和 '+' 给你一个列表,你可以检查它的长度等。

=====================

在您的argv 测试中

if len(sys.argv) > 2:
    chosen = int(sys.argv[2])
    chdos = "at_dos"+sys.argv[2]+".dat"

sys.argv 是一个列表,因此如果有足够的元素来应用 sys.argv[2] 步骤,则 len 计数。

这不起作用,因为args.dos 是单个字符串,而不是列表。

if len(args.dos) > 1:
    chosen = int(args.dos[0])
    chdos = "at_dos"+args.dos[0]+".dat"

len(args.dos) 是字符串中的字符数,args.dos[0] 是第一个字符。

============

如果我定义:

def get_dos(argv=None):
    parser=argparse.ArgumentParser()
    parser.add_argument('--dos', type=int, nargs='?')
    args = parser.parse_args(argv)
    chosen = args.dos
    if chosen is not None:
        chdos = 'at_dos%s.dat'%chosen
    else:
        chdos = ''
    return chosen, chdos

这些测试产生的值我认为符合您的需求:

In [1042]: get_dos([])
Out[1042]: (None, '')

In [1043]: get_dos(['--dos'])
Out[1043]: (None, '')

In [1044]: get_dos(['--dos','123'])
Out[1044]: (123, 'at_dos123.dat')

【讨论】:

  • 您好,感谢您的回复。虽然这是有效的,但我正在努力让解析器部分脱离 def(--dos 可能是其他选项)。字节感谢
【解决方案2】:

您需要替换 nargs = "?"使用 nargs = "*"。将 nargs 设置为“?”表示将有 1 个可选参数。您想要的是一个可选参数列表,即“*”。像这样。

import argparse
parser = argparse.ArgumentParser(description="output parser")
group = parser.add_mutually_exclusive_group()
group.add_argument("--dos", help="get DOSCAR for plot",
               nargs="*", metavar=("int"))
args = parser.parse_args()

if args.dos:    
    if len(args.dos) > 1:
        chosen = int(args.dos[0])
        chdos = "at_dos"+args.dos[0]+".dat"
    else:
        chosen = None

    inpt = "DOSY"
    print(chosen)
    print(inpt)

【讨论】:

  • 我已经尝试过 nargs = "*"。你检查过代码吗?它给出了同样的问题。
【解决方案3】:

感谢所有回复的人,特别是@hpaulj。但他们都没有真正解决我的问题。所以,我采取了其他方式。为了完整起见,我将其发布在这里。

#!/usr/bin/python3
import argparse

parser = argparse.ArgumentParser(description="output parser")
group = parser.add_mutually_exclusive_group()
group.add_argument("--dos", help="get DOSCAR for plot",action='store_true')
parser.add_argument("-n", help="Showing last n line",
                    metavar='integer', type=int)

args = parser.parse_args()
if args.dos:
    if args.n:
        chosen = int(args.n)
        chdos = "at_dos"+str(args.n)+".dat"
    else:
        chosen = None
    inpt = "DOSY"
    print(inpt)
    print(chosen)

正确产生预期结果:

$python3 tt.py --dos
DOSY
None

$python3 tt.py --dos -n 222
DOSY
222

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2021-11-11
    • 2018-06-29
    • 2021-09-02
    • 1970-01-01
    • 2014-10-11
    • 2017-08-20
    • 2012-01-27
    • 2017-02-23
    相关资源
    最近更新 更多