[python] 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.')



답변

아니요, argparse에는 상호 포괄적 인 옵션 집합 을 만드는 옵션이 없습니다 .

이를 처리하는 가장 간단한 방법은 다음과 같습니다.

if args.prox and (args.lport is None or args.rport is None):
    parser.error("--prox requires --lport and --rport.")


답변

조건부로 필요한 인수에 대해 이야기하고 있습니다. @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수신합니다 . 이것은 또한 보장 과 서로 간의 독립적 인 행동을 가지고있다.TrueFalse--prox-lport-rport


답변

parser.parse_known_args()메서드 를 사용 하고있는 경우 필수 인수로 --lport--rport인수 를 추가하는 것은 어떻습니까 --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도움말 메시지에 표시되지 않습니다

답변

설정되지 않은 lport경우 사용하세요 prox. 그렇지 않다면, 왜하지 lportrport의 인수 prox? 예 :

parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')

그러면 사용자가 입력하는 시간이 절약됩니다. 테스트 if args.prox is not None:if args.prox:.


답변

받아 들여진 대답은 나를 위해 잘 작동했습니다! 모든 코드가 테스트없이 깨 졌기 때문에 여기에서 내가 받아 들인 대답을 테스트 한 방법입니다. 오류를 발생 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"])

unittests로

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"])

영감을받은 : unittest를 사용하여 argparse 테스트-종료 오류


답변