Python argparse从无限集合中选择
我有下面的代码来创建一个容器,它假装像所有素数的集合(实际上隐藏了一个记忆的暴力素数测试) 到目前为止,这似乎是可行的:Python argparse从无限集合中选择,python,math,iteration,containers,argparse,Python,Math,Iteration,Containers,Argparse,我有下面的代码来创建一个容器,它假装像所有素数的集合(实际上隐藏了一个记忆的暴力素数测试) 到目前为止,这似乎是可行的: >>> primes = Primes() >>> 7 in primes True >>> 104729 in primes True >>> 100 in primes False >>> 100 not in primes True 但是它不能很好地处理argparse: >
>>> primes = Primes()
>>> 7 in primes
True
>>> 104729 in primes
True
>>> 100 in primes
False
>>> 100 not in primes
True
但是它不能很好地处理argparse
:
>>> import argparse as ap
>>> parser = ap.ArgumentParser()
>>> parser.add_argument('prime', type=int, choices=primes, metavar='p')
_StoreAction(option_strings=[], dest='prime', nargs=None, const=None, default=None, type=<type 'int'>, choices=<__main__.Primes object at 0x7f4e21783f10>, help=None, metavar='p')
>>> parser.parse_args(['7'])
Namespace(prime=7)
>>> parser.parse_args(['11'])
Namespace(prime=11)
>>> parser.parse_args(['12'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/argparse.py", line 1688, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "/usr/lib/python2.7/argparse.py", line 1720, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/usr/lib/python2.7/argparse.py", line 1929, in _parse_known_args
stop_index = consume_positionals(start_index)
File "/usr/lib/python2.7/argparse.py", line 1885, in consume_positionals
take_action(action, args)
File "/usr/lib/python2.7/argparse.py", line 1778, in take_action
argument_values = self._get_values(action, argument_strings)
File "/usr/lib/python2.7/argparse.py", line 2219, in _get_values
self._check_value(action, value)
File "/usr/lib/python2.7/argparse.py", line 2267, in _check_value
tup = value, ', '.join(map(repr, action.choices))
TypeError: argument 2 to map() must support iteration
>将argparse作为ap导入
>>>parser=ap.ArgumentParser()
>>>add_参数('prime',type=int,choices=primes,metavar='p')
_StoreAction(选项_strings=[],dest='prime',nargs=None,const=None,default=None,type=,choices=,help=None,metavar='p')
>>>parser.parse_args(['7'])
名称空间(prime=7)
>>>parser.parse_args(['11'])
名称空间(prime=11)
>>>parser.parse_args(['12'])
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
parse_args中的文件“/usr/lib/python2.7/argparse.py”,第1688行
args,argv=self.parse\u known\u args(args,名称空间)
parse_known_args中的文件“/usr/lib/python2.7/argparse.py”,第1720行
名称空间,args=self.\u解析\u已知\u args(args,名称空间)
文件“/usr/lib/python2.7/argparse.py”,第1929行,在已知参数中
停止索引=使用位置(开始索引)
文件“/usr/lib/python2.7/argparse.py”,第1885行,位置
采取行动(行动,参数)
文件“/usr/lib/python2.7/argparse.py”,第1778行,在take_action中
参数值=self.\u获取值(操作、参数字符串)
文件“/usr/lib/python2.7/argparse.py”,第2219行,在获取值中
自我检查值(动作、值)
文件“/usr/lib/python2.7/argparse.py”,第2267行,在检查值中
tup=value,','.join(映射(repr,action.choices))
TypeError:映射()的参数2必须支持迭代
你就这么说吧
任何支持in运算符的对象都可以作为选项传递
值,所以dict对象、set对象、自定义容器等都是
支持
显然,我不想迭代无限的素数“集合”。那么为什么
argparse
试图map
我的素数呢?它不是只需要中的和不在中吗?获取异常的来源非常清楚,请查看:
if action.choices is not None and value not in action.choices:
tup = value, ', '.join(map(repr, action.choices))
msg = _('invalid choice: %r (choose from %s)') % tup
raise ArgumentError(action, msg)
支票本身没有问题。它试图打印出一条有用的错误消息,试图为您提供所有可能的选择。我想,如果您定义迭代器只返回字符串primes
作为其repr
的内容,您可能会对其进行黑客攻击,使其执行正确的操作。这是一个文档错误。这是2019年8月由
编写的库要求choices
参数不仅是一个容器,而且是一个iterable,它试图列出可用的选项,这对您的案例不起作用。您可以尝试通过给它一个伪\uuuu iter\uuuuu
来破解它,该伪只返回一些信息字符串。选项
用于可以枚举所有允许值(有限(小)集)的参数。文件应该更清楚地说明这一点
素数
是一个无限集。您可以设置type
参数来引发非素数的ValueError。谢谢,我按照您的建议创建了一个问题。2019年Python中仍然存在此错误:(
if action.choices is not None and value not in action.choices:
tup = value, ', '.join(map(repr, action.choices))
msg = _('invalid choice: %r (choose from %s)') % tup
raise ArgumentError(action, msg)