#python #python-3.x #parameter-passing #command-line-arguments #argparse
#python #аргументы командной строки #argparse
Вопрос:
У меня есть программа, которая использует имя и пароль по умолчанию. Я использую argparse, чтобы позволить пользователю указывать параметры командной строки, и я хотел бы разрешить пользователю предоставлять программе другое имя и пароль для использования. Итак, у меня есть следующее:
parser.add_argument(
'-n',
'--name',
help='the login name that you wish the program to use'
)
parser.add_argument(
'-p',
'--password',
help='the password to log in with.'
)
Но нет никакого смысла указывать только имя или только пароль, но было бы разумно не указывать ни один. Я заметил, что argparse имеет возможность указать, что два аргумента являются взаимоисключающими. Но у меня есть два аргумента, которые должны отображаться вместе. Как мне добиться такого поведения? (Я нашел «группы аргументов», упомянутые в документах, но, похоже, они не решают мою проблему http://docs.python.org/2/library/argparse.html#argument-groups )
Комментарии:
1. И я предполагаю, что постобработка аргументов выходит за рамки вопроса?
2. Ни о чем не может быть и речи. Я просто хочу, чтобы argparse выполнил всю работу за меня и сообщил пользователю, что параметры должны отображаться вместе.
Ответ №1:
Я считаю, что лучший способ справиться с этим — это постобработать возвращенное пространство имен. Причина, по которой argparse
это не поддерживается, заключается в том, что он анализирует аргументы по 1 за раз. Легко argparse
проверить, было ли что-то уже проанализировано (именно поэтому взаимоисключающие аргументы работают), но нелегко увидеть, будет ли что-то проанализировано в будущем.
Простой:
parser.add_argument('-n','--name',...,default=None)
parser.add_argument('-p','--password',...,default=None)
ns = parser.parse_args()
if len([x for x in (ns.name,ns.password) if x is not None]) == 1:
parser.error('--name and --password must be given together')
name = ns.name if ns.name is not None else "default_name"
password = ns.password if ns.password is not None else "default_password"
похоже, этого будет достаточно.
Комментарии:
1. Это правильно, но ‘name = ns.name или «default_name» ‘ проще и, на мой взгляд, легче читать это’ns.name если ns.name is not None else …». Однако, как указывает mgilson в другом месте, если пользователь передает пустую строку для любого значения,пустая строка будет иметь значение false, и вместо предоставленной пустой строки будет использоваться значение по умолчанию.
2.
sum(1 for x in (ns.name, ns.password) if x is not None)
также работает вместоlen([x for x in (ns.name,ns.password) if x is not None])
.3. Этого было бы
ns.name is None ^ ns.password is None
недостаточно? : D
Ответ №2:
Я знаю, что это опоздало более чем на два года, но я нашел хороший и краткий способ сделать это:
if bool(ns.username) ^ bool(ns.password):
parser.error('--username and --password must be given together')
^
является оператором XOR в Python. Требовать оба аргумента, заданных в командной строке, по сути, является проверкой XOR.
Комментарии:
1. Разве это не должно быть XNOR?
2. @KaustubhKarkare
XOR
оценивается так, какTrue
если бы указывались только имя пользователя или пароль. Выше описан случай сбоя в таком состоянии, так и должно бытьXOR
.
Ответ №3:
Вероятно, именно так я бы это и сделал. Поскольку у вас есть существующие значения по умолчанию с возможностью изменения, определите значения по умолчанию, но не используйте их в качестве аргументов по умолчанию:
default_name = "x"
default_pass = "y"
parser.add_argument(
'-n',
'--name',
default=None,
help='the login name that you wish the program to use'
)
parser.add_argument(
'-p',
'--password',
default=None,
help='the password to log in with.'
)
args = parser.parse_args()
if all(i is not None for i in [args.name, args.password]):
name = args.name
passwd = args.password
elif any(i is not None for i in [args.name, args.password]):
parser.error("Both Name and Password are Required!")
else:
name = default_name
passwd = default_pass
Комментарии:
1. Будьте осторожны с этим. Что, если пользователь устанавливает свой пароль в пустую строку?
2. В качестве примечания вы всегда можете отредактировать свой удаленный ответ и отменить его удаление 🙂
3. Спасибо, это немного раздражает, когда он там висит.
4. Что ж, более того, если бы вы получили 10 голосов и галочку, вы могли бы получить значок просветленного 🙂
5. спасибо, и обновлено с проверкой на отсутствие, а не на ложность.