Что init.py для?
что это __init__.py
для исходного каталога Python?
11 ответов
это часть пакета. вот документация.
на
__init__.py
файлы необходимы, чтобы Python рассматривал каталоги как содержащие пакеты; это делается для предотвращения каталогов с общим именем, таким какstring
, от непреднамеренного скрытия допустимых модулей, которые возникают позже (глубже) на пути поиска модуля. В простейшем случае__init__.py
может быть просто пустой файл, но он также может выполнять код инициализации пакета или установить__all__
переменной, описанной позже.
файлы с именем __init__.py
используются для пометки каталогов на диске как каталогов пакетов Python.
Если у вас есть файлы
mydir/spam/__init__.py
mydir/spam/module.py
и mydir
находится на вашем пути, вы можете импортировать код в module.py
as
import spam.module
или
from spam import module
если убрать __init__.py
file, 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
здесь, я могу начать новый сеанс, используя синтаксис ниже. Этот код будет таким же, выполняемым изнутри или снаружи каталога пакета "база данных".
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/
мнение большинства, кажется, что __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.
Регистрация 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.module
references:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __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 * так, глядя на наш пример выше снова, если мы хотели импортировать подмодули в subpackage __all__
переменная subpackage/__init__.py
будет:
__all__ = ['submodule1', 'submodule2']
С __all__
переменная заполняется так, когда вы выполняете
from subpackage import *
он будет импортировать submodule1 и submodule2.
Как видите,__init__.py
может быть очень полезно, кроме его основной функции указания, что каталог является модуль.
это облегчает импорт других файлов python. Когда вы разместили этот файл в каталоге (скажем, материал), содержащем другие файлы py, вы можете сделать что-то вроде импорта материала.другой.
root\
stuff\
other.py
morestuff\
another.py
без этого __init__.py
внутри материала каталога вы не можете импортировать other.py, потому что Python не знает, где находится исходный код для материала, и не может распознать его как пакет.
хотя Python работает без __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
to __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