Используйте argparse для запуска 1 из 2 функций в моем скрипте

В настоящее время у меня есть 2 функции в моем сценарии .py.

№1 подключается к базе данных и выполняет некоторую обработку.

# 2 выполняет некоторую другую обработку файлов

В настоящее время, прежде чем запускать скрипт, я должен вручную прокомментировать/раскомментировать функцию, которую я хочу запустить в своем main блоке операторов if.

Как я могу использовать argparse, чтобы он спрашивал меня, какую функцию запускать при запуске моего скрипта?


person Blankman    schedule 08.02.2011    source источник


Ответы (3)


Можно сообщить объектам ArgumentParser о функции или объекте, который имеет желаемое поведение, напрямую, с помощью пар action='store_const' и const=<stuff> в вызове add_argument() или с помощью вызова set_defaults() (последний наиболее полезен, когда вы используете субпарсеры). Если вы сделаете это, вы сможете найти свою функцию в объекте parsed_args, который вы получите в результате синтаксического анализа, вместо того, чтобы, скажем, искать его в глобальном пространстве имен.

В качестве небольшого примера:

import argparse

def foo(parsed_args):
    print "woop is {0!r}".format(getattr(parsed_args, 'woop'))

def bar(parsed_args):
    print "moop is {0!r}".format(getattr(parsed_args, 'moop'))

parser = argparse.ArgumentParser()

parser.add_argument('--foo', dest='action', action='store_const', const=foo)
parser.add_argument('--bar', dest='action', action='store_const', const=bar)
parser.add_argument('--woop')
parser.add_argument('--moop')

parsed_args = parser.parse_args()
if parsed_args.action is None:
    parser.parse_args(['-h'])
parsed_args.action(parsed_args)

И тогда вы можете назвать это так:

% python /tmp/junk.py --foo                                           
woop is None
% python /tmp/junk.py --foo --woop 8 --moop 17                        
woop is '8'
% python /tmp/junk.py --bar --woop 8 --moop 17                        
moop is '17'
person Matt Anderson    schedule 09.02.2011
comment
хорошо, это должно быть в моем блоке if name__==__main? - person Blankman; 09.02.2011
comment
Если файл python предназначен для доступа несколькими способами (вызывается как скрипт, загружается как модуль из другого файла python), то части, специфичные для запуска в качестве скрипта, должны быть в вашем основном разделе. Вы можете написать функцию main() и вызвать ее в блоке __name__ == "__main__" if или написать код действия сценария непосредственно в указанном блоке if. - person Matt Anderson; 09.02.2011
comment
Разве это решение не заставит нас указывать унисон всех аргументов как необязательный? У меня более сложный случай, когда foo и bar имеют разные наборы аргументов, и я хочу не указывать их все как необязательные. - person Jabro; 25.02.2021

Если это просто флаг запуска A или B, то простой аргумент «store_true» должен подойти.

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--run_a_not_b', action='store_true')
_StoreTrueAction(option_strings=['--run_a_not_b'], dest='run_a_not_b', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('--run_a_not_b')
>>> parsed_args = parser.parse_args('--run_a_not_b'.split())
>>> if parsed_args.run_a_not_b:
    print "run a"
else:
    print "run b"


run a
>>> parsed_args = parser.parse_args(''.split())
>>> if parsed_args.run_a_not_b:
    print "run a"
else:
    print "run b"


run b

Или, если вы действительно хотите передать имя вызываемой функции, вы можете сделать это таким (несколько хакерским) способом:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--func_to_run', type=str)
_StoreAction(option_strings=['--func_to_run'], dest='func_to_run', nargs=None, const=None, default=None, type=<type 'str'>, choices=None, help=None, metavar=None)
>>> parsed_args = parser.parse_args('--func_to_run my_other_func'.split())
>>> parsed_args.func_to_run
'my_other_func'
>>> f = globals()[parsed_args.func_to_run]
<function my_other_func at 0x011F6670>
>>> f()

edit : для обработки целочисленного аргумента достаточно указать тип

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--run_a_not_b', action='store_true')
>>> parser.add_argument('--func_arg', type=int)
>>> parsed_args = parser.parse_args('--run_a_not_b --arg 42'.split())
>>> parsed_args = parser.parse_args('--run_a_not_b --func_arg 42'.split())
>>> parsed_args
Namespace(func_arg=42, run_a_not_b=True)

Таким образом, вы можете просто получить parsed_args.func_arg за значение, если выберете в этом примере.

person Daniel DiPaolo    schedule 08.02.2011
comment
если один из них имеет один целочисленный параметр, становится ли это сложнее? Спасибо! - person Blankman; 09.02.2011
comment
Не намного сложнее, вы также можете принять это как аргумент, отредактируйте мой ответ - person Daniel DiPaolo; 09.02.2011

Вы можете рассмотреть возможность использования ткани для этого.

person Josh Bleecher Snyder    schedule 08.02.2011