Как переключить логическую опцию argparse?

Я пытаюсь объединить configparser и argparse для скрипта, чтобы значения по умолчанию для различных аргументов, определенных argparse, сохранялись в файле конфигурации, которым управляют через configparser. Проблема, с которой я сталкиваюсь, связана с логическими параметрами. argparse имеет действия store_true и store_false для этих параметров, которые автоматически создают значение по умолчанию и указывают, что следует изменить при задании параметра. Однако, поскольку значение по умолчанию считывается из файла конфигурации, я заранее не знаю, что это такое, чтобы использовать эти действия. Это предполагает что-то вроде:

import argparse,configparser

config = configparser.ConfigParser()
config['DEFAULT']['test'] = 'False'
config.read('testing.cfg')

parser = argparse.ArgumentParser()

if config.getboolean('DEFAULT','test'):
    parser.add_argument('-t',action='store_false', dest='test')
else:
    parser.add_argument('-t',action='store_true', dest='test')

args = parser.parse_args()

print(args.test)

Однако мне не нравится идея иметь операторы parser.addargument внутри условного выражения (особенно громоздко, если у меня есть больше этих опций). Я бы предпочел что-то вроде:

parser.add_argument('-t',action='toggle_boolean',dest='test',default=config.getboolean('DEFAULT','test'))

В этом случае действие toggle_boolean переключит состояние логического значения, каким бы оно ни было, когда задан аргумент. Проблема в том, что указанного действия (toggle_boolean) не существует. Как мне определить такое действие или есть лучший способ сделать это?


person rpspringuel    schedule 24.04.2018    source источник


Ответы (1)


store_true и store_false являются частными случаями store_const:

In [213]: parser = argparse.ArgumentParser()
In [214]: foo = True
In [215]: parser.add_argument('-s', action='store_const', default=foo, const=not(foo))
In [216]: parser.add_argument('-n', action='store_const', default=not(foo), const=foo);

In [218]: parser.parse_args([])
Out[218]: Namespace(n=False, s=True)

In [219]: parser.parse_args(['-s','-n'])
Out[219]: Namespace(n=True, s=False)
person hpaulj    schedule 24.04.2018
comment
Идеальный. Никаких новых строк кода не требуется и делает именно то, что мне нужно. - person rpspringuel; 25.04.2018
comment
Я бы рекомендовал писать not foo вместо функционального not(foo). Возможно, здесь это не вызывает проблем, но такая привычка приводит к таким сюрпризам, как запись not(x) in y и ожидание, что она будет вести себя как (not x) in y вместо not (x in y). - person user2357112 supports Monica; 25.04.2018