问题:Argparse:如果存在“ x”,则必需的参数“ y”
我的要求如下:
./xyifier --prox --lport lport --rport rport
对于参数prox,我使用action =’store_true’来检查它是否存在。我不需要任何论点。但是,如果设置了–prox,我也需要 rport和lport。有没有一种简单的方法可以使用argparse做到这一点,而无需编写自定义条件编码。
更多代码:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', type=int, help='Listen Port.')
non_int.add_argument('--rport', type=int, help='Proxy port.')
回答 0
不,argparse中没有任何选项可以构成相互包含的选项集。
解决此问题的最简单方法是:
if args.prox and (args.lport is None or args.rport is None):
parser.error("--prox requires --lport and --rport.")
回答 1
您是在说要有条件地要求参数。就像@borntyping所说的那样,您可以检查错误并执行parser.error()
,或者可以应用与--prox
添加新参数时相关的要求。
您的示例的简单解决方案可能是:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', required='--prox' in sys.argv, type=int)
non_int.add_argument('--rport', required='--prox' in sys.argv, type=int)
这种方式required
接收True
还是False
取决于用户是否使用过--prox
。这也保证了-lport
和-rport
相互之间的独立行为。
回答 2
如果存在,如何使用--lport
和--rport
args --prox
。
# just add --prox arg now
non_int = argparse.ArgumentParser(description="stackoverflow question",
usage="%(prog)s [-h] [--prox --lport port --rport port]")
non_int.add_argument('--prox', action='store_true',
help='Flag to turn on proxy, requires additional args lport and rport')
opts, rem_args = non_int.parse_known_args()
if opts.prox:
non_int.add_argument('--lport', required=True, type=int, help='Listen Port.')
non_int.add_argument('--rport', required=True, type=int, help='Proxy port.')
# use options and namespace from first parsing
non_int.parse_args(rem_args, namespace = opts)
还请记住,您可以提供opts
第一次解析后生成的命名空间,而第二次解析其余参数。这样,最后,在完成所有解析之后,您将拥有一个包含所有选项的命名空间。
缺点:
- 如果
--prox
不存在,则命名空间中甚至不存在其他两个从属选项。尽管根据您的用例(如果--prox
不存在),则其他选项的发生无关紧要。 - 需要修改用法消息,因为解析器不知道完整结构
--lport
并且--rport
不显示在帮助消息中
回答 3
未设置lport
时使用prox
。如果不是,为什么不进行lport
和的rport
论证prox
?例如
parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')
这样可以节省用户输入的时间。测试if args.prox is not None:
和一样容易if args.prox:
。
回答 4
接受的答案对我很有用!由于所有代码都未经测试就被破坏,这就是我测试接受答案的方式。parser.error()
不会引发argparse.ArgumentError
错误,而是退出该过程。您必须进行测试SystemExit
。
与pytest
import pytest
from . import parse_arguments # code that rasises parse.error()
def test_args_parsed_raises_error():
with pytest.raises(SystemExit):
parse_arguments(["argument that raises error"])
有单元测试
from unittest import TestCase
from . import parse_arguments # code that rasises parse.error()
class TestArgs(TestCase):
def test_args_parsed_raises_error():
with self.assertRaises(SystemExit) as cm:
parse_arguments(["argument that raises error"])
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。