可选位置参数的Argparse值

时间:2018-11-09 15:29:31

标签: python argparse

我正在尝试创建一个argparse可选参数,该参数可能-OR-可能没有关联的输入值。我想要以下行为:
 1.未指定参数,值= None
 2.参数指定了一个值,值= user_input
 3.指定的参数不带值,value =源自位置值

前两个很简单。这是我不知道的第三个。我发现2篇类似的文章:
python argparse optional positional argument with detectable switch
对于没有值的可选参数,此值将默认值设置为常量。
Argparse optional positional arguments?
这个主题很接近,但不是我所需要的(他从系统调用中获取默认值):
我希望根据位置值确定我的位置。

我创建的简单示例代码:

parser = argparse.ArgumentParser()
parser.add_argument('input')
parser.add_argument('-c', '--csv', nargs='?')
parser.add_argument('-p', '--pnf', nargs='?')

设置输入并打印时:

args = parser.parse_args('my.h5 -c my_file.csv --pnf'.split())
print ('Input = %s' % args.input)
print ('CSV file = %s' % args.csv)
print ('PNF file = %s' % args.pnf)

我得到:

Input = my.h5
CSV file = my_file.csv
PNF file = None

如果我将输入修改为:

args = parser.parse_args('my.h5 -c'.split())

结果输出为:

Input = my.h5
CSV file = None
PNF file = None

Value = None时,我无法判断可选参数是否未定义,或者是否已定义但没有值。在第二种情况下,我想从位置参数派生CSV文件名(在此示例中,派生名称为my.csv)。当定义--pnf时,我想做同样的事情(默认情况下,以上的默认PNF为my.pnf)。有办法吗?

4 个答案:

答案 0 :(得分:2)

  

我无法判断可选参数是否未定义,或者是否已定义但没有值

如果您创建解析器like this

parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)

现在可以区分这三种情况。

  • 如果传递了-c val,它将以值args出现在"val"中。
  • 如果-c是不带任何值的传递,它将在args中以值None出现。
  • 如果-c被完全省略,则它不会出现在args中。

-p也是如此。

答案 1 :(得分:0)

使用const参数:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('input')
parser.add_argument('-c', '--csv', nargs='?', const='foobar')
parser.add_argument('-p', '--pnf', nargs='?', const='foobar')

args = parser.parse_args()
print(args)

if args.csv and args.csv=='foobar':
    args.csv = args.input

args.pnf = args.input if (args.pnf and args.pnf=='foobar') else args.pnf

print(args)

您的两个示例输入:

0933:~/mypy$ python3 stack53228663.py my.h5 -c my_file.csv --pnf
Namespace(csv='my_file.csv', input='my.h5', pnf='foobar')
Namespace(csv='my_file.csv', input='my.h5', pnf='my.h5')

0933:~/mypy$ python3 stack53228663.py my.h5 -c
Namespace(csv='foobar', input='my.h5', pnf=None)
Namespace(csv='my.h5', input='my.h5', pnf=None)

答案 2 :(得分:0)

为了完整性(和将来参考),我将发布使用argument_default=argparse.SUPPRESS时获取参数所需的修改代码。见下文:

parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
parser.add_argument('input')
parser.add_argument('-c', '--csv', nargs='?')
parser.add_argument('-p', '--pnf', nargs='?')
args = parser.parse_args('my.h5 -c my_file --pnf'.split())
for d_key, d_val in vars(args).items() :
  print (d_key, d_val)

输出结果:

input my.h5
csv my_file
pnf None

对于第二组输入

args = parser.parse_args('my.h5 -c'.split())
print(vars(args))
for d_key, d_val in vars(args).items() :
  print (d_key, d_val)

输出看起来像这样:

input my.h5
csv None

答案 3 :(得分:0)

根据@hpaulj的早期评论,这显示了我使用default=False, const=True实现的逻辑。

parser = argparse.ArgumentParser()
parser.add_argument('input')
parser.add_argument('-c', '--csv', nargs='?', default=False, const=True)
parser.add_argument('-p', '--pnf', nargs='?', default=False, const=True)
args = parser.parse_args('my.h5 -c'.split())
print(vars(args))
HDF5_FILE = args.input
if isinstance(args.csv, str) :
  CSV_FILE = args.csv
elif args.csv :
  CSV_FILE=HDF5_FILE[:-3] + '_v3_stress.csv'
else :
  CSV_FILE = ''
# repeat above logic for args.pnf
print ('input=', HDF5_FILE, ',  csv=', CSV_FILE, ' pnf=', PNF_FILE )

结果输出如下:

{'input': 'my.h5', 'csv': True, 'pnf': False}
hdf5= my.h5 ,  csv= my_v3_stress.csv  pnf= 

修改后的'parse_args()'和结果输出:

args = parser.parse_args('my.h5 -c my_file.csv -p'.split())

礼物:

{'input': 'my.h5', 'csv': 'my_file.csv', 'pnf': True}
hdf5= my.h5 ,  csv= my_file.csv  pnf= my_v3_stress.nrf

如果要检查的变量很多,可以将if/elif/else逻辑移至返回所需值的def