Функция 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 не очень дружественное средство в таких случаях.
Функция Python main с примерами: __main__
Здесь у нас есть два фрагмента на вывод, один из которых определен в функции main — «Hello World», а другой — «Guru99». Когда вы запускаете функцию def main():
Выводится только «Guru99»
а не код «Hello World».
Это потому, что мы не объявили функцию вызова «if__name __ ==» __main__».
Когда интерпретатор Python читает исходный файл, он выполняет весь найденный в нем код.
Когда Python запускает «исходный файл» в качестве основной программы, он устанавливает для специальной переменной (__name__) значение («__main__»).
Когда вы выполняете функцию main, она читает оператор «if» и проверяет, действительно ли __name__ равно __main__.
В Python «if__name __ ==« __main__ » позволяет запускать файлы Python как многократно используемые модули или как отдельные программы.
Как и C, Python использует == для сравнения, а = для назначения. Интерпретатор Python использует функцию main двумя способами:
импорт: __name __ = имя файла модуля — если оператор == false, скрипт в __main__ не будет выполнен
прямой запуск: __ name __ = __ main__ — если Statement == True, скрипт в _main_ будет выполнен
поэтому, когда код выполняется, он проверяет имя модуля с помощью «if».
Важно, чтобы после определения функции main вы вызывали код с помощью if__name __ == «__main__», а затем запускали код, только тогда вы получите вывод «hello world!» в консоли программирования, как показано ниже.

Примечание. Убедитесь, что после определения функции main вы задали некоторый отступ и не объявляете код прямо под функцией def main(): в противном случае она выдаст ошибку отступа.
__main__ — Кодове середовище верхнього рівня¶
У Python спеціальна назва __main__ використовується для двох важливих конструкцій:
- ім’я середовища верхнього рівня програми, яке можна перевірити за допомогою виразу __name__ == ‘__main__’ ; і
- файл __main__.py в пакетах Python.
Обидва ці механізми пов’язані з модулями Python; як користувачі взаємодіють з ними та як вони взаємодіють один з одним. Вони детально пояснюються нижче. Якщо ви новачок у роботі з модулями Python, ознайомтеся з розділом посібника Модулі .
__name__ == ‘__main__» ¶
Коли імпортується модуль або пакет Python, __name__ встановлюється на ім’я модуля. Зазвичай це назва самого файлу Python без розширення .py :
>>> import configparser >>> configparser.__name__ 'configparser'
Якщо файл є частиною пакета, __name__ також включатиме шлях до батьківського пакета:
>>> from concurrent.futures import process >>> process.__name__ 'concurrent.futures.process'
Однак, якщо модуль виконується в кодовому середовищі верхнього рівня, його __name__ встановлюється на рядок ‘__main__’ .
Що таке «середовище коду верхнього рівня»?¶
__main__ — це назва середовища, де виконується код верхнього рівня. «Код верхнього рівня» — це перший зазначений користувачем модуль Python, який запускається. Це «верхній рівень», тому що він імпортує всі інші модулі, які потрібні програмі. Іноді «код верхнього рівня» називають точкою входу до програми.
Кодове середовище верхнього рівня може бути:
-
область дії інтерактивної підказки:
>>> __name__ '__main__'
$ python helloworld.py Hello, world!
$ python -m tarfile usage: tarfile.py [-h] [-v] (. )
$ echo "import this" | python The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. .
$ python -c "import this" The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. .
У кожній із цих ситуацій __name__ модуля верхнього рівня встановлено на ‘__main__’ .
Як наслідок, модуль може виявити, чи працює він у середовищі верхнього рівня, перевіряючи власне __name__ , що дозволяє загальну ідіому для умовного виконання коду, коли модуль не ініціалізовано оператором імпорту: :
if __name__ == '__main__': # Execute when the module is not initialized from an import statement. .
Для більш детального ознайомлення з тим, як __name__ встановлюється в усіх ситуаціях, перегляньте розділ підручника Модулі .
Ідіоматичне використання¶
Деякі модулі містять код, призначений лише для використання сценарієм, як-от аналіз аргументів командного рядка або отримання даних зі стандартного введення. Якщо подібний модуль було імпортовано з іншого модуля, наприклад, для модульного тестування, код сценарію також буде ненавмисно виконано.
Тут стане в нагоді використання блоку коду if __name__ == ‘__main__» . Код у цьому блоці не працюватиме, якщо модуль не буде виконано в середовищі верхнього рівня.
Putting as few statements as possible in the block below if __name__ == ‘__main__’ can improve code clarity and correctness. Most often, a function named main encapsulates the program’s primary behavior:
# echo.py import shlex import sys def echo(phrase: str) -> None: """A dummy wrapper around print.""" # for demonstration purposes, you can imagine that there is some # valuable and reusable logic inside this function print(phrase) def main() -> int: """Echo the input arguments to standard output""" phrase = shlex.join(sys.argv) echo(phrase) return 0 if __name__ == '__main__': sys.exit(main()) # next section explains the use of sys.exit
Зауважте, що якби модуль не інкапсулював код у функцію main , а поміщав його безпосередньо в блок if __name__ == ‘__main__’ , змінна phrase буде глобальною для весь модуль. Це загрожує помилками, оскільки інші функції в модулі можуть ненавмисно використовувати глобальну змінну замість локального імені. Функція main вирішує цю проблему.
Використання функції main має додаткову перевагу в тому, що сама функція echo є ізольованою та її можна імпортувати в інше місце. Коли імпортується echo.py , функції echo і main будуть визначені, але жодна з них не буде викликана, оскільки __name__ != ‘__main__’ .
Зауваження щодо упаковки¶
Функції main часто використовуються для створення інструментів командного рядка, вказуючи їх як точки входу для сценаріїв консолі. Коли це зроблено, pip вставляє виклик функції в сценарій шаблону, де повернуте значення main передається в sys.exit() . Наприклад:
sys.exit(main())
Оскільки виклик main загорнутий у sys.exit() , очікується, що ваша функція поверне деяке значення, прийнятне як вхідні дані для sys.exit() ; як правило, ціле число або None (що неявно повертається, якщо ваша функція не має оператора return).
By proactively following this convention ourselves, our module will have the same behavior when run directly (i.e. python echo.py ) as it will have if we later package it as a console script entry-point in a pip-installable package.
Зокрема, будьте обережні щодо повернення рядків з вашої функції main . sys.exit() інтерпретує рядковий аргумент як повідомлення про помилку, тому ваша програма матиме код виходу 1 , що вказує на помилку, і рядок буде записано в sys.stderr . Приклад echo.py з попереднього прикладу використання угоди sys.exit(main()) .
Посібник користувача з пакування Python містить колекцію посібників і довідок про те, як розповсюджувати та встановлювати пакунки Python за допомогою сучасних інструментів.
__main__.py в пакетах Python¶
Якщо ви не знайомі з пакетами Python, перегляньте розділ пакети підручника. Найчастіше файл __main__.py використовується для забезпечення інтерфейсу командного рядка для пакета. Розглянемо наступний гіпотетичний пакет, «bandclass»:
bandclass ├── __init__.py ├── __main__.py └── student.py
__main__.py буде виконано, коли сам пакет викликається безпосередньо з командного рядка за допомогою прапорця -m . Наприклад:
$ python -m bandclass
Ця команда призведе до запуску __main__.py . Те, як ви використовуєте цей механізм, залежатиме від характеру пакету, який ви пишете, але в цьому гіпотетичному випадку може мати сенс дозволити вчителю шукати учнів:
# bandclass/__main__.py import sys from .student import search_students student_name = sys.argv[1] if len(sys.argv) >= 2 else '' print(f'Found student: search_students(student_name)>')
Зауважте, що from .student import search_students є прикладом відносного імпорту. Цей стиль імпорту можна використовувати під час посилань на модулі в пакеті. Для отримання додаткової інформації перегляньте Внутрішньопакетні посилання у розділі Модулі підручника.
Ідіоматичне використання¶
The content of __main__.py typically isn’t fenced with an if __name__ == ‘__main__’ block. Instead, those files are kept short and import functions to execute from other modules. Those other modules can then be easily unit-tested and are properly reusable.
Якщо використовується, блок if __name__ == ‘__main__’ все одно працюватиме належним чином для файлу __main__.py у пакеті, тому що його атрибут __name__ включатиме шлях до пакета, якщо імпортовано
>>> import asyncio.__main__ >>> asyncio.__main__.__name__ 'asyncio.__main__'
Однак це не працюватиме для файлів __main__.py у кореневому каталозі файлу .zip. Тому для узгодженості бажано використовувати мінімальний __main__.py , наприклад venv , згаданий нижче.
See venv for an example of a package with a minimal __main__.py in the standard library. It doesn’t contain a if __name__ == ‘__main__’ block. You can invoke it with python -m venv [directory] .
Перегляньте runpy для отримання додаткової інформації про прапорець -m для виконуваного файлу інтерпретатора.
Перегляньте zipapp , щоб дізнатися, як запускати програми, упаковані у файли .zip. У цьому випадку Python шукає файл __main__.py в кореневому каталозі архіву.
імпорт __main__ ¶
Незалежно від того, з якого модуля була запущена програма Python, інші модулі, що працюють у цій же програмі, можуть імпортувати область верхнього рівня середовища ( namespace ), імпортуючи модуль __main__ . Це імпортує не файл __main__.py , а будь-який модуль, який отримав спеціальну назву ‘__main__’ .
Ось приклад модуля, який використовує простір імен __main__ :
# namely.py import __main__ def did_user_define_their_name(): return 'my_name' in dir(__main__) def print_user_name(): if not did_user_define_their_name(): raise ValueError('Define the variable `my_name`!') if '__file__' in dir(__main__): print(__main__.my_name, "found in file", __main__.__file__) else: print(__main__.my_name)
Приклад використання цього модуля може бути наступним:
# start.py import sys from namely import print_user_name # my_name = "Dinsdale" def main(): try: print_user_name() except ValueError as ve: return str(ve) if __name__ == "__main__": sys.exit(main())
Тепер, якби ми запустили нашу програму, результат виглядав би так:
$ python start.py Define the variable `my_name`!
Код виходу програми буде 1, що вказуватиме на помилку. Розкоментування рядка my_name = «Dinsdale» виправляє програму, і тепер вона завершує роботу з кодом статусу 0, що вказує на успіх:
$ python start.py Dinsdale found in file /path/to/start.py
Зауважте, що імпорт __main__ не викликає жодних проблем із ненавмисним запуском коду верхнього рівня, призначеного для використання сценарію, який розміщено в if __name__ == «__main__» блоку start модуля . Чому це працює?
Python inserts an empty __main__ module in sys.modules at interpreter startup, and populates it by running top-level code. In our example this is the start module which runs line by line and imports namely . In turn, namely imports __main__ (which is really start ). That’s an import cycle! Fortunately, since the partially populated __main__ module is present in sys.modules , Python passes that to namely . See Special considerations for __main__ in the import system’s reference for details on how this works.
Python REPL є ще одним прикладом «середовища верхнього рівня», тому все, що визначено в REPL, стає частиною області __main__ :
>>> import namely >>> namely.did_user_define_their_name() False >>> namely.print_user_name() Traceback (most recent call last): . ValueError: Define the variable `my_name`! >>> my_name = 'Jabberwocky' >>> namely.did_user_define_their_name() True >>> namely.print_user_name() Jabberwocky
Зауважте, що в цьому випадку область __main__ не містить атрибут __file__ , оскільки вона інтерактивна.
Область __main__ використовується в реалізації pdb і rlcompleter .
№37 Функция __main__ / для начинающих
В различных руководствах по Python часто используется функция main() . Но иногда это может быть и лишним.
Лаконичность — важный элемент программирования. И вполне логично задавать вопрос о том, зачем разработчику добавлять лишние строки в программу. Функция main() требует дополнительных строк, но она служит определенной цели.
В этом материале речь пойдет о функции main() , о том, какую пользу она приносит, а также о том, как правильно использовать ее в коде.
Что такое функция main()?
Main — это специальная функция, которая позволяет добавить больше логики в структуру программ. В Python можно вызвать функцию в нижней части программы, которая и будет запущена. Рассмотрим такой пример:
def cookies():
print("Печенье вкусное!")
print("Дайте печенье.")
cookies()Запустим этот код:
Дайте печенье. Печенье вкусное!Можно увидеть, что выражение «Дайте печенье.» выводится до «Печенье вкусное!», потому что метод cookies() не вызывается вплоть до последней строки, а именно в этой функции хранится предложение «Печенье вкусное!».
Такой код работает, но его довольно сложно читать. В таких языках программирования, как C++ и Java весь основной код программы хранится внутри основной функции. Это хороший способ для распределения всего кода программы. Те, кто только знакомится с Python, но уже работал, например, с C++ будут благодарны за использование функции main() .
Как создать функцию main
Есть две части основной функции Python. Первая — сама функция main() . В ней хранится код основной программы. Вызовем функцию cookies() и выведем выражение «Дайте печенье.» из функции main() :
def cookies():
print("Печенье вкусное!")
def main():
print("Дайте печенье.")
cookies()Теперь вызовем функцию в конце программы:
main()Можно запустить код:
Дайте печенье. Печенье вкусное!Результат не поменялся. Но теперь сам код читать легче. Пусть в нем и больше строк (и одна дополнительная строка), вполне очевидно, что именно происходит:
- Cookies() — функция, которая выводит «Печенье вкусное!».
- Когда программа запускается, определяются две функции: cookies() и main() .
- Затем функция main() вызывается.
- «Дайте печенье.» выводится в консоли.
- Затем вызывается функция cookies() , которая выводит в консоль «Печенье вкусное!».
Код не только чище, но и логичнее. Если вы пришли из другого языка, например, Java, но знаете, насколько это удобно.
Значение __name__
Прежде чем переходить к инструкциям __name__ и __main__ , которые часто используются вместе, нужно обсудить __name__ . __name__ хранит название программы.
Если запустить файл прямо, то значением __name__ будет __main__ . Предположим, что файл называется print_name.py :
print(__name__)Этот код можно запустить следующим образом:
$ python print_name.pyОн вернет __main__ .
Предположим, что этот код был импортирован в качестве модуля в файл main.py :
import print_name$ python main.pyprint_nameКод внутри print_name.py исполняется потому что он был импортирован в качестве модуля в основной программе. Файл print_name выводит __name__ в консоль. Поскольку print_name был импортирован в качестве модуля, то и значением __name__ является print_name .
if __name__ == __main__ в Python
Вы наверняка встречали следующую конструкцию в программах на Python в функции main :
if __name__ == "__main__":Что она значит? В Python любая переменная, начинающаяся с двух символов нижнего подчеркивания ( __ ), является специальной. Это зарезервированные значения, которые выполняют определенную роль в программе.
__main__ указывает на область видимости, где будет выполняться код. Если запустить Python-файл прямо, то значением __name__ будет __main__ . Если же его запустить в качестве модуля, то значением будет уже не __main__ , а название модуля.
Это значит, что строка выше вернет True только в том случае, если программа будет запущена прямо.
Если же ссылаться на файл как на модуль, то содержимое конструкции if не будет выполнено. Рассмотрим на примере.
Как использовать __name__ и __main__
Создадим новый скрипт на Python под названием username.py. В коде будем просить пользователя ввести его имя и проверять, не является ли его длина больше 5. Если символов не больше 5, то попросим ввести имя снова.
Начнем с определения глобальной переменной для хранения имени пользователя:
