Использование вывода argparse для вызова функций - PullRequest
11 голосов
/ 11 августа 2010

В настоящее время мой код выглядит следующим образом.Это позволяет мне анализировать несколько параметров, которые получает мой программный скрипт.Есть ли другой способ, который ближе к «лучшим практикам»?На самом деле я не видел кода, использующего вывод argparse, только как его настроить.

def useArguments():
    x = 0
    while x <= 5:
        if x == 0:                      
            if args.getweather != None:
                getWeather(args.getweather)
        if x == 1:
            if args.post != None:
                post(args.post)
        if x == 2:
            if args.custompost != None:
                custompost(args.custompost)
        if x == 3:
            if args.list != None:
                listAccounts(args.list)
        if x == 4:
            if args.add != None:
                addAccount(args.add[0])
        if x == 5:
            if args.edit != None:
                editAccount(args.edit[0])
        x = x + 1    


if __name__ == '__main__':

    updateConfig()

    parser = argparse.ArgumentParser(description='Post Yahoo weather to Twitter.', epilog="Report any bugs to example@email.com", prog='Program')

    parser.add_argument('-a', '--add', nargs=1, help='Add a new account. Use the desired account name as an argument.')
    parser.add_argument('-e', '--edit', nargs=1, choices=accountListSTR[:-1], help='Edit an account. Use the desired account name as an argument.')
    parser.add_argument('-g', '--getweather', nargs='*', choices=accountListSTR, help='Get weather and post here. Specify account(s) as argument. Use "all" for all accounts. If you specify multiple accounts, separate by a space NOT a comma.')
    parser.add_argument('-p', '--post', nargs='*', choices=accountListSTR, help='Post weather to Twitter. Specify account(s) as argument. Use "all" for all accounts. If you specify multiple accounts, separate by a space NOT a comma.')
    parser.add_argument('-c', '--custompost', nargs=2, help='Post a custom message. Specify an account then type the message. Make sure you use "" around the message. Use "all" for all accounts.')
    parser.add_argument('-l', '--list', action='store_const', const='all', help='List all accounts.')
    parser.add_argument('--version', action='version', version='%(prog)s 0.3.3')

    args = parser.parse_args()

    useArguments()

Ответы [ 3 ]

11 голосов
/ 11 августа 2010

Вы можете предоставить пользовательское действие для аргумента by, и я цитирую:

, передавая объект, реализующий API-интерфейс Action.Самый простой способ сделать это - расширить argparse.Action, предоставив соответствующий метод __call__.Метод __call__ должен принимать четыре параметра:

  1. parser : объект ArgumentParser, содержащий это действие.
  2. пространство имен :объект пространства имен, который будет возвращен parse_args().Большинство действий добавляют атрибут к этому объекту.
  3. values ​​: связанные аргументы командной строки, с любыми примененными преобразованиями типов. (Преобразования типов задаются с аргументом ключевого слова типа для add_argument().
  4. option_string : строка параметра, которая использовалась для вызова этого действия. Аргумент option_string является необязательным и будет отсутствовать, если действие связано с позиционным аргументом.
6 голосов
/ 13 ноября 2010

См. http://docs.python.org/library/argparse.html#sub-commands:

Один особенно эффективный способ обработки подкоманд - объединить использование метода add_subparsers() с вызовами set_defaults(), чтобы каждый подпарсер знал, какую функцию Python он должен выполнять.

В двух словах:

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

weather_parser = subparsers.add_parser('get-weather')
weather_parser.add_argument('--bar')
weather_parser.set_defaults(function=get_weather)  # !

args = parser.parse_args(['get-weather', '--bar', 'quux'])
print args.function(args)

Здесь мы создаем подпапку для команды get-weather и назначаем ей функцию get_weather.

Обратите внимание, что в документации сказано, что ключевое слово / атрибут называется func, но оно определенно function по состоянию на argparse 1.1.

Результирующий код немного многословен, поэтому я опубликовал небольшой пакет "argh" , который упрощает задачу, например ::

parser = argparse.ArgumentParser()
add_commands(parser, [get_weather])
print dispatch(parser, ['get-weather', '--bar', 'quux'])

"Argh" может сделать больше, но я позволю переполнению стека ответить на это. : -)

4 голосов
/ 11 августа 2010

За исключением --version, который обычно является опцией, предоставленные вами действия лучше рассматривать как "подкоманды".

Мне не известны особенности argparse, так как яЯ пока не пробовал Python 2.7, но вы можете взглянуть на команду svn в качестве примера, вот несколько псевдокодов для командной строки:

myprog [--version] <command> [<command opts>...]

Где <command> in:

add|edit|getweather|post|custompost|list

И <command opts> - это параметры, специфичные для этой команды.Используя optparse (который похож), это будет означать, что ваша команда будет возвращена в args при вызове parse_args, что позволит вам сделать что-то вроде этого:

opts, args = parser.parse_args()
if opts.version:
    ...
else:
    getattr("do_" + args[0])(*args[1:])

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

...