【问题标题】:using a variable keyword for an optional argument name with python argparse在 python argparse 中使用变量关键字作为可选参数名称
【发布时间】:2016-03-26 21:20:19
【问题描述】:

我正在为我正在编写的 python 脚本使用 argparse。该脚本的目的是处理存储表格数据的大型 ascii 文件。该脚本只是为我编写的一个类提供了一个方便的前端,它允许对表格数据进行任意数量的即时剪切。在类中,用户可以传入一个变量名关键字参数,其中包含一个绑定到变量的二元素元组。元组定义了名称对应于变量名关键字的任何列的下限和上限。例如:

reader = AsciiFileReducer(fname, mass = (100, float("inf")), spin = (0.5, 1))

这个 reader 实例将忽略输入 fname 的所有行,除了那些 mass > 1000.5 。输入 fname 可能有许多其他列,但只有 massspin 会在它们上放置剪切。

我希望我正在编写的脚本保留此功能,但我不知道如何允许使用 argparse.add_argument 添加具有变量名的参数。我的类允许任意数量的可选参数,每个参数都有未指定的名称,其中为名称选择的字符串本身是有意义的。 python 的 **kwargs 特性使这成为可能。 argparse 可以吗?

【问题讨论】:

  • 这取决于您希望如何指定命令行参数。那会是 `-c "mass > 100" -c "0.5
  • 经过更多的挖掘,我想我可能已经找到了一种使用 nargs 组合并允许相同可选参数多次出现的 hack-y 解决方法。我想如果我允许可选参数-row_cut_min-row_cut_max,并设置nargs=2,那么第一个参数可以是列的字符串名称,第二个参数可以是cut。我认为这给出了我想要的行为,不是吗?
  • 实际上,我认为这不允许我想要的,因为它不允许-row_cut_min 或-row_cut_max 的多次出现。所以我又回到了绘图板上。

标签: python argparse


【解决方案1】:

通过 argparse 接受任意 key:value 对的问题之前已经出现过。例如:

Using argparse with function that takes **kwargs argument

这有几个很长的答案,带有指向早期问题的链接。

另一种选择是获取一个字符串并用 JSON 解析它。

但这里有一个基于nargsappend 操作类型的快速选择:

parser=argparse.ArgumentParser()
parser.add_argument('-k','--kwarg',nargs=3,action='append')

一个示例输入,生成一个带有列表列表的命名空间:

args=parser.parse_args('-k mass 100 inf -k spin 0.5 1.0'.split())

Namespace(kwarg=[['mass', '100', 'inf'], ['spin', '0.5', '1.0']])

可以将它们转换为具有如下表达式的字典:

vargs={key:(float(v0),float(v1)) for key,v0,v1 in args.kwarg}

可以传递给你的函数:

foo(**vargs)
{'spin': (0.5, 1.0), 'mass': (100.0, inf)}

【讨论】:

  • 感谢@hpaulj 提供可靠、清晰的答案。不知道为什么我的搜索没有找到你之前给出的答案。这直接解决了我的问题。
【解决方案2】:

如果我不完全理解您想要做什么,请提前道歉。但是根据您的描述,如果我正在实施此操作,我可能会尝试以下操作。这里我做了质量和自旋可选输入并设置它们的默认值,所以唯一需要的输入是文件名。

示例代码:

# q.py test code

import argparse

parser = argparse.ArgumentParser(prog='q.py')
parser.add_argument('file', help='filename')
parser.add_argument('-m', default=100, type=int, help='integer mass value')
parser.add_argument('-s', nargs=2, default=[0.5,1.0], type=float, help='spin values without comma')

args=parser.parse_args()

print('file:', args.file)
print('mass:', args.m)
print('spin:', tuple(args.s))

一些命令行调用:

$ python q.py -h
usage: q.py [-h] [-m M] [-s S S] file

positional arguments:
file        filename

optional arguments:
-h, --help  show this help message and exit
-m M        integer mass value
-s S S      spin values without comma

$ python q.py test.csv
file: test.csv
mass: 100
spin: (0.5, 1.0)

$ python q.py test.csv -m 99 -s 0.2 1.1
file: test.csv
mass: 99
spin: (0.2, 1.1)

我认为您可以像这样调用初始化您的阅读器:

reader = AsciiFileReducer(args.file, mass = (args.m, float("inf")), spin = tuple(args.s))

【讨论】:

  • 感谢您的插话,史蒂夫,我想我的问题可能表述得不够清楚。问题是我需要避免显式声明参数名称。
猜你喜欢
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 2023-02-06
  • 2016-09-27
  • 2017-12-05
  • 2021-03-06
  • 1970-01-01
  • 2019-05-27
相关资源
最近更新 更多