Ответы:
Раньше он был обязательной частью пакета ( старый, до 3.3 «обычный пакет» , а не более новый 3.3+ «пакет пространства имен» ).
Python определяет два типа пакетов, обычные пакеты и пакеты пространства имен. Обычные пакеты - это традиционные пакеты, которые существовали в Python 3.2 и более ранних версиях. Обычный пакет обычно реализуется как каталог, содержащий
__init__.py
файл. Когда обычный пакет импортируется, этот__init__.py
файл выполняется неявно, и определяемые им объекты привязываются к именам в пространстве имен пакета.__init__.py
Файл может содержать один и тот же код Python , что любой другой модуль может содержать, и Python будет добавить некоторые дополнительные атрибуты модуля , когда он импортируется.
Но просто нажмите на ссылку, она содержит пример, дополнительную информацию и объяснение пакетов пространства имен, типа пакетов без __init__.py
.
sys.path.insert(0, '/path/to/datetime')
замену этого пути путем к любому каталогу, который вы только что создали. Теперь попробуйте что-то вроде from datetime import datetime;datetime.now()
. Вы должны получить AttributeError (потому что он импортирует ваш пустой файл сейчас). Если вы повторите эти шаги без создания пустого файла инициализации, этого не произойдет. Это то, что он призван предотвратить.
from datetime import datetime
ошибку без ошибок. Это хорошо, вплоть до версии 2.3!
builtins
перечисляет встроенные функции и классы , а не встроенные модули (см. Docs.python.org/3/tutorial/modules.html#the-dir-function ). Если вы хотите перечислить встроенные модули , сделайте import sys; print(sys.builtin_module_names)
(см. Docs.python.org/3/library/sys.html#sys.builtin_module_names ).
Названные __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
Файл обычно пустой, но может быть использован для экспорта отдельных частей пакета под более удобным названием, трюмные удобные функции и т.д. Учитывая приведенную выше пример, содержимое модуля инициализации можно обращаться как
import spam
основываясь на этом
__init__.py
требовался в Python 2.X и все еще требуется в Python 2.7.12 (я проверял его), но он больше не требуется (предположительно) начиная с Python 3.3 и далее, и не требуется в Python 3.4.3 (I проверил это). См. Stackoverflow.com/questions/37139786 для получения дополнительной информации.
__init__.py
.
setup.py
и вы используете, find_packages()
необходимо иметь __init__.py
в каждом каталоге. См stackoverflow.com/a/56277323/7127824
В дополнение к маркировке каталога как пакета Python и определению __all__
, __init__.py
позволяет определить любую переменную на уровне пакета. Это часто удобно, если пакет определяет что-то, что будет часто импортироваться, в стиле API. Эта модель способствует приверженности питонской философии «квартира лучше вложенного».
Вот пример из одного из моих проектов, в котором я часто импортирую sessionmaker
вызываемый Session
для взаимодействия с моей базой данных. Я написал пакет базы данных с несколькими модулями:
database/
__init__.py
schema.py
insertions.py
queries.py
My __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/
По мнению большинства, __init__.py
файлы должны быть очень тонкими, чтобы не нарушать философию «явный лучше, чем неявный».
engine
, sessionmaker
, create_engine
, И os
все это может также быть импортировано из database
... похоже , как ты напутал это пространство имен.
__all__ = [...]
для ограничения импорта import *
. Но кроме этого, да, у вас осталось грязное пространство имен верхнего уровня.
Есть 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
может быть полезным иногда, но не всегда.
__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
ссылки:
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
Следовательно, используя * import, модуль пакета зависит от __init__.py
содержимого.
from package_x.subPackage_b.module_n1 import function_X
Хотя 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
__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
>>>
Это облегчает импорт других файлов Python. Когда вы помещаете этот файл в каталог (скажем, вещи), содержащий другие файлы py, вы можете сделать что-то вроде import stuff.other.
root\
stuff\
other.py
morestuff\
another.py
Без этого __init__.py
внутри каталога вы не смогли бы импортировать other.py, потому что Python не знает, где находится исходный код материала, и не может распознать его как пакет.
__init__.py
Файл делает импорт легко. Когда __init__.py
в пакете присутствует an , функцию a()
можно импортировать из файла b.py
следующим образом:
from b import a
Без этого, однако, вы не можете импортировать напрямую. Вы должны изменить системный путь:
import sys
sys.path.insert(0, 'path/to/b.py')
from b import a