Argparse Взаимоисключающие группы не работают над парой позиционных и необязательных аргументов - PullRequest
0 голосов
/ 11 сентября 2018

Я написал код, в котором мне нужен входной файл в качестве аргумента командной строки. Я хочу, чтобы пользователь предоставил это двумя способами:

  1. с использованием флага --input, например:

    python3 prog.py --input A.cpp

  2. просто без флага

    python3 prog.py A.cpp

оба должны работать одинаково.

Я написал программу для него, используя argparse.

#!/usr/bin/env python3
import argparse
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    input_file = parser.add_mutually_exclusive_group()
    input_file.add_argument('inp',nargs='?',help='file name')
    input_file.add_argument('--input',dest='inp',help='file name')
    args = parser.parse_args()
    print(args)

Отлично работает для:

$ python3 prog.py A.cpp
Namespace(inp='A.cpp')

пока не для:

$ python3 prog.py --input A.cpp
Namespace(inp=None)

Я хочу, чтобы оба способа были взаимоисключающими, а их значение - сохранять место назначения (как я это сделал здесь inp). Человек может пропустить оба. означает, что они не требуются.

Как мне этого достичь?

1 Ответ

0 голосов
/ 11 сентября 2018

Проблема с общим dest. По умолчанию позиционный перезаписывает значение необязательного.

In [13]: p = argparse.ArgumentParser()
In [14]: a1 = p.add_argument('--foo')
In [15]: a2 = p.add_argument('bar', nargs='?', default='default')

In [16]: p.parse_args('xxx'.split())
Out[16]: Namespace(bar='xxx', foo=None)

In [17]: p.parse_args('--foo 1'.split())
Out[17]: Namespace(bar='default', foo='1')

Изменить, чтобы они разделяли dest:

In [18]: a1.dest = 'bar'

Необязательный анализируется, затем позиционный. Так как это '?', Значение по умолчанию помещается в пространство имен, вместо записи предыдущего значения

In [19]: p.parse_args('--foo 1'.split())
Out[19]: Namespace(bar='default')

Здесь необязательное значение over записывает позиционное значение:

In [20]: p.parse_args('xxx --foo 1'.split())
Out[20]: Namespace(bar='1')

Здесь явное позиционное значение над записью опций:

In [21]: p.parse_args('--foo 1 xxx'.split())
Out[21]: Namespace(bar='xxx')

Я понимаю разницу тонкую. Это связано с тем, как анализируются позиционные и дополнительные функции (поочередно), а также с обработкой позиционного nargs='?'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...