Избегайте повторного документирования скрипта и функции - PullRequest
0 голосов
/ 20 февраля 2019

При написании скрипта я иногда использую функцию, чтобы точно описать, что делает скрипт.Это потому, что я мог бы хотеть вызвать функцию из кода или запустить ее как скрипт.Есть ли способ избежать повторения документации аргументов функции в строках справки в argparse?Например:

import argparse
def my_function(arg_one, arg_two):
    """
    arg_one: The first argument.
    arg_two: The second argument.
    """
    print("The first argument is %r" % arg_one)
    print("The second argument is %r" % arg_two)

if __name__=="main":
    parser = argparse.ArgumentParser()
    parser.add_argument('--arg-one', help="The first argument.")
    parser.add_argument('--arg-two', help="The second argument.")
    args = parser.parse_args()
    my_function(args.arg_one, args.arg_two)

Поскольку аргументы функции и сценария точно совпадают, вы можете видеть, что мне приходилось документировать их дважды («Первый аргумент», «Второй аргумент»).Это тривиальная проблема, но это действительно раздражает.Должен ли я просто не использовать функцию вообще?

1 Ответ

0 голосов
/ 20 февраля 2019

Вот как я бы это написал ...

""" My Crazy Program
Usage:
    my_prog [options]

Options:
"""

def my_function(file_output, file_input, recursive=False):
    """
    output=str: specifies an output path
    input=str: specifies an input path
    recursive: apply recursively
    """
    print("The first argument is %r" % file_output)
    print("The second argument is %r" % file_input)
    print("The third argument is %r" % recursive)

# This is where the magic happens
__doc__ += '\n'.join(f'   --{parsed[0]: <15}  {parsed[1]}'
                     for parsed in (
                         line.strip().split(': ') 
                         for line in my_function.__doc__.split('\n'))
                     if len(parsed) == 2)

if __name__ == "__main__":
    from docopt import docopt
    ARGS = docopt(__doc__)
    my_function(ARGS['--output'], ARGS['--input'], ARGS['--recursive'])

Хорошо, вы видите магическую линию (начиная с __doc__ += ...), она создает документацию для модуля, которая становится:

 My Crazy Program
Usage:
    my_prog [options]

Options:
   --output=str       specifies an output path
   --input=str        specifies an input path
   --recursive        apply recursively

Затем docopt анализирует и возвращает этот словарь:

$ python my_prog
{'--input': None,
 '--output': None,
 '--recursive': False}

$ python my_prog --output /dev/null --recursive
{'--input': None,
 '--output': '/dev/null',
 '--recursive': True}

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

The first argument is '/dev/null'
The second argument is None
The third argument is True

Мне нравится эторешение, потому что это одна строка, но я согласен с вами, что это не красиво, я позволю вам написать свою собственную красивую функцию, которая делает это автоматически для каждого файла: o)

...