На главную
  Статьи
  Статьи Python



  Написать мне
 
 

Функция main() для Python.

Перевод статьи Гвидо ван Россума, рассказывающей о том, как следует оформлять функцию main().

Хочу предложить программистам функцию main(), которую удобно использовать в различном контексте. Например в интерактивном режиме Python, когда вам хочется поэкспериментировать.

В свое время, я определял функцию main() различным образом. Приблизительно так:

"""Описание модуля.

Подробное описание использования.
"""
import sys
import getopt

def main():
    # Разбираем аргументы командной строки
    try:
        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
    except getopt.error, msg:
        print msg
        print "для справки используйте --help"
        sys.exit(2)
    # process options
    for o, a in opts:
        if o in ("-h", "--help"):
            print __doc__
            sys.exit(0)
    # Анализируем
    for arg in args:
        process(arg) # process() определен в другом месте

if __name__ == "__main__":
    main()

Я уверен, что многие пишут нечто подобное main() функции. Несколько предложений, которые сделают эту функцию более гибкой. Тем более, что синтаксический анализ опций становится все более сложным.

Во первых, добавим дополнительный аргумент argv. Так, чтобы можно было вызывать функцию в интерактивном режиме:

def main(argv=None):
    if argv is None:
        argv = sys.argv
        # и т.д. заменяя sys.argv на argv в getopt запросах

Обратите внимание, что мы заполняем значения по умолчанию динамически. Это более гибко, чем:

def main(argv=sys.argv):
    # и т.д.

Таким образом теперь мы можем изменить параметры вызова в любой момент времени.

Вызов sys.exit() закрывает сессию интерпретатора. Доработаем программу:

if __name__ == "__main__":
    sys.exit(main())

Вызов sys.exit(main()) вернет результат функции.

Другое усовершенствование касается использования исключения Usage(), которое мы перехватываем в main:

import sys
import getopt

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "h", ["help"])
        except getopt.error, msg:
             raise Usage(msg)
        # more code, unchanged
    except Usage, err:
        print >>sys.stderr, err.msg
        print >>sys.stderr, "for help use --help"
        return 2

if __name__ == "__main__":
    sys.exit(main())

Теперь мы имеем единственную точку выхода из функции, что предпочтительнее множественных return 2. Это также облегчает повторный анализ параметров: raise Usage вызывается просто во вспомогательной функции.

Вы можете возразить, что можно перенести конструкцию try/except из main() в конец модуля (if __name__ == "__main__": ...). Но это привело бы к возникновению ошибки при вызове в интерактивном режиме интерпретатора.

Однако, обобщение может быть полезным: определите другое исключение (возможно Error), которое обрабатывается так же, как и Usage, но возвращает 1. Его можно применять для ожидаемых ошибок типа отказа открыть необходимые файлы. Не ситаксические ошибки командной строки, но ожидаемые ситуации. Т.к. traceback не очень дружественное средство в таких случаях.



Источник: www.python.ru

Автор: Гвидо ван Россум
Перевод: Орехов А.И.











Hosted by uCoz