11 ответов:
Это часть пакета. вот документация.
Файлы
__init__.pyнеобходимы для того, чтобы Python рассматривал каталоги как содержащие пакеты; это делается для предотвращения непреднамеренного сокрытия допустимых модулей, которые встречаются позже (глубже) в пути поиска модуля. В простейшем случае__init__.pyможет быть просто пустым файлом, но он также может выполнить код инициализации для пакета или задать переменную__all__, описанную выше. позже.
Файлы с именем
__init__.pyиспользуются для обозначения каталогов на диске как каталогов пакетов Python. Если у вас есть файлыmydir/spam/__init__.py mydir/spam/module.pyИ
mydirнаходится на вашем пути, вы можете импортировать код вmodule.pyкакimport spam.moduleИли
from spam import moduleЕсли вы удалите файл
__init__.py, Python больше не будет искать подмодули в этом каталоге, поэтому попытки импортировать модуль завершатся неудачей.Файл
__init__.pyобычно пуст, но может быть использован для экспорта выбранных частей пакета под более удобное имя, функции удержания удобства и т. д. В приведенном выше примере содержимое модуля init можно получить в видеimport spamНа основе этого
В дополнение к маркировке каталога как пакета Python и определению
__all__,__init__.pyпозволяет определить любую переменную на уровне пакета. это часто удобно, если пакет определяет что-то, что будет импортироваться часто, подобно API. Этот паттерн способствует приверженности питоновской философии "плоское лучше вложенного".Пример
Вот пример из одного из моих проектов, в котором я часто импортирую
sessionmakerпод названиемSessionв взаимодействуйте с моей базой данных. Я написал пакет "база данных" с несколькими модулями:database/ __init__.py schema.py insertions.py queries.pyМой
__init__.pyсодержит следующий код:import os from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine engine = create_engine(os.environ['DATABASE_URL']) Session = sessionmaker(bind=engine)Поскольку я определяю
Sessionздесь, я могу начать новый сеанс, используя синтаксис ниже. Этот код будет таким же, выполняемым изнутри или снаружи каталога пакета "database".from database import Session session = Session()Конечно, это небольшое удобство - альтернативой было бы определить
Sessionв новом файле типа "create_session.py - в моем пакете базы данных, и начните новые сеансы, используя:from database.create_session import Session session = Session()Дальнейшее чтение
Есть довольно интересная нить reddit, охватывающая соответствующие применения
__init__.pyздесь:Http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/
Большинство считает, что файлы должны быть очень тонкими, чтобы не нарушать философию" явное лучше, чем неявное".
Есть 2 основные причины для
__init__.py
Для удобства: другим пользователям не нужно будет знать точное расположение ваших функций в иерархии пакетов.
your_package/ __init__.py file1.py/ file2.py/ ... fileN.py # in __init__.py from file1 import * from file2 import * ... from fileN import * # in file1.py def add(): passТогда другие могут вызвать add () с помощью
from your_package import addНе зная file1, как
from your_package.file1 import addЕсли вы хотите, чтобы что-то было инициализировано; например, ведение журнала (который должен быть помещен на верхний уровень):
import logging.config logging.config.dictConfig(Your_logging_config)
Файл
__init__.pyзаставляет Python рассматривать каталоги, содержащие его, как модули.Кроме того, это первый файл, загружаемый в модуль, поэтому вы можете использовать его для выполнения кода, который вы хотите запускать каждый раз, когда модуль загружается, или указать подмодули, подлежащие экспорту.
Поскольку Python 3.3,
__init__.pyбольше не требуется определять каталоги как импортируемые пакеты Python.Check PEP 420: неявные пакеты пространства имен :
Встроенная поддержка каталогов пакетов, которые не требуют
__init__.pyфайлов маркеров и могут автоматически охватывать несколько сегментов пути (вдохновленные различными сторонними подходами к пакетам пространств имен, как описано в PEP 420)Вот тест:
$ mkdir -p /tmp/test_init $ touch /tmp/test_init/module.py /tmp/test_init/__init__.py $ tree -at /tmp/test_init /tmp/test_init ├── module.py └── __init__.py $ python3 >>> import sys >>> sys.path.insert(0, '/tmp') >>> from test_init import module >>> import test_init.module $ rm -f /tmp/test_init/__init__.py $ tree -at /tmp/test_init /tmp/test_init └── module.py $ python3 >>> import sys >>> sys.path.insert(0, '/tmp') >>> from test_init import module >>> import test_init.moduleReferences:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
это __init__.py не требуется для пакетов в Python 3?
В Python определение пакета очень простое. Как и Java, иерархическая структура и структура каталогов одинаковы. Но вы должны иметь
__init__.pyв пакете. Я объясню файл__init__.pyна примере ниже:package_x/ |-- __init__.py |-- subPackage_a/ |------ __init__.py |------ module_m1.py |-- subPackage_b/ |------ __init__.py |------ module_n1.py |------ module_n2.py |------ module_n3.py
__init__.pyможет быть пустым, пока он существует. Это означает, что каталог следует рассматривать как пакет. Конечно,__init__.pyтакже может задать соответствующий контент.Если мы добавим функцию в module_n1:
def function_X(): print "function_X in module_n1" returnПосле работает:
>>>from package_x.subPackage_b.module_n1 import function_X >>>function_X() function_X in module_n1Затем мы последовали за пакетом иерархии и вызвали функцию module_n1. Мы можем использовать
__init__.pyв subPackage_b следующим образом:__all__ = ['module_n2', 'module_n3']После запуска:
>>>from package_x.subPackage_b import * >>>module_n1.function_X() Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named module_n1Следовательно, используя * импорт, пакет модуля подчиняется содержимому
__init__.py.
__init__.pyбудет рассматривать каталог, в котором он находится, как загружаемый модуль.Для тех, кто предпочитает читать код, я помещаю здесь комментарий Двухбитового алхимика.
$ find /tmp/mydir/ /tmp/mydir/ /tmp/mydir//spam /tmp/mydir//spam/__init__.py /tmp/mydir//spam/module.py $ cd ~ $ python >>> import sys >>> sys.path.insert(0, '/tmp/mydir') >>> from spam import module >>> module.myfun(3) 9 >>> exit() $ $ rm /tmp/mydir/spam/__init__.py* $ $ python >>> import sys >>> sys.path.insert(0, '/tmp/mydir') >>> from spam import module Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named spam >>>
Что такое __init__.py используется для чего?
В
__init__.pyдля инициализации пакетов Python. Самый простой способ продемонстрировать это-взглянуть на структуру стандартного модуля Python.Как вы можете видеть в приведенной выше структуре, включение файлаpackage/ __init__.py file.py file2.py file3.py subpackage/ __init__.py submodule1.py submodule2.py__init__.pyв каталог указывает интерпретатору Python, что каталог должен рассматриваться как пакет PythonЧто входит в
__init__.py?
__init__.pyможет быть Ан пустой файл, но он часто используется для выполнения установки, необходимой для пакета (импорт вещей, загрузка вещей в путь и т. д.).Одна общая вещь, которую нужно сделать в вашем
__init__.py, - это импортировать выбранные классы, функции и т. д. на уровень пакета, чтобы их можно было удобно импортировать из пакета.В приведенном выше примере мы можем сказать, что file.py имеет файл класса. Поэтому без чего-либо в нашем
__init__.pyвы импортировали бы с помощью этого синтаксиса:from package.file import FileОднако вы можете импортировать файл в свой
__init__.pyчтобы сделать его доступным на уровне пакета:# in your __init__.py from file import File # now import File from package from package import FileЕще одна вещь, которую нужно сделать, - это на уровне пакета сделать доступными подпакеты/модули с переменной
__all__. Когда интерпетер видит переменную__all__, определенную в переменной__init__.py, он импортирует модули, перечисленные в переменной__all__, Когда вы делаете:from package import *
__all__это список, содержащий имена модулей, которые вы хотите импортировать с помощью import * так что посмотрите на наш приведенный выше пример еще раз, если мы хотим импортировать подмодули в подпакет переменная__all__вsubpackage/__init__.pyбудет иметь вид:__all__ = ['submodule1', 'submodule2']С переменной
__all__, заполненной таким образом, когда вы выполняетеfrom subpackage import *Он будет импортировать submodule1 и submodule2.
Как вы можете видеть,
__init__.pyможет быть очень полезным, помимо своей основной функции указания, что каталог является модулем.
Это облегчает импорт других файлов python. Когда вы помещаете этот файл в каталог (скажем, stuff), содержащий другие файлы py, вы можете сделать что-то вроде импорта материала.другой.
root\ stuff\ other.py morestuff\ another.pyБез этого
__init__.pyвнутри каталога вы не сможете импортировать данные other.py, потому что Python не знает, где находится исходный код для материала, и не может распознать его как пакет.
Хотя Python работает без файла
__init__.py, Вы все равно должны включить его.Он указывает, что пакет должен рассматриваться как модуль, поэтому включите его (даже если он пуст).
Существует также случай, когда вы можете фактически использовать файл
__init__.py:представьте, что у вас есть следующая структура файлов:
main_methods |- methods.pyИ
methods.pyсодержали следующее:def foo(): return 'foo'Для использования
foo()вам потребуется одно из следующих действий:from main_methods.methods import foo # Call with foo() from main_methods import methods # Call with methods.foo() import main_methods.methods # Call with main_methods.methods.foo()Может быть там вам нужно (или вы хотите) сохранить
methods.pyВнутриmain_methods(например, время выполнения/зависимости), но вы хотите только импортироватьmain_methods.
Если вы изменили имя
methods.pyна__init__.py, то вы можете использоватьfoo(), просто импортировавmain_methods:import main_methods print(main_methods.foo()) # Prints 'foo'Это работает, потому что
__init__.pyрассматривается как часть пакета.
Некоторые пакеты Python действительно делают это. Примером может служить JSON , где запуск
import jsonфактически является импортом__init__.pyиз пакетаjson(см. структура файла пакета здесь):Исходный код:
Lib/json/__init__.py
Comments