Python определяет два типа пакетов, обычные пакеты и пакеты пространства имен. Обычные пакеты - это традиционные пакеты, которые существовали в Python 3.2 и более ранних версиях. Обычный пакет обычно реализуется как каталог, содержащий __init__.pyфайл. Когда обычный пакет импортируется, этот __init__.pyфайл выполняется неявно, и определяемые им объекты привязываются к именам в пространстве имен пакета. __init__.pyФайл может содержать один и тот же код Python , что любой другой модуль может содержать, и Python будет добавить некоторые дополнительные атрибуты модуля , когда он импортируется.
Но просто нажмите на ссылку, она содержит пример, дополнительную информацию и объяснение пакетов пространства имен, типа пакетов без __init__.py.
Что это значит: «это сделано для предотвращения непреднамеренного скрытия действительными модулями каталогов с общим именем, например, строки, которые встречаются позже в пути поиска модулей»?
Карл Дж
97
@CarlG Python ищет список каталогов для разрешения имен, например, в операторах импорта. Поскольку это может быть любой каталог, а конечный пользователь может добавить произвольные каталоги, разработчикам приходится беспокоиться о каталогах, которые имеют одинаковое имя с допустимым модулем Python, например, «string» в примере с документами. Чтобы облегчить это, он игнорирует каталоги, которые не содержат файл с именем _ _ init _ _.py (без пробелов), даже если он пуст.
Двухразрядный алхимик
186
@CarlG Попробуй это. Создайте каталог с именем datetime и создайте в нем два пустых файла: файл init.py (с подчеркиванием) и datetime.py. Теперь откройте интерпретатор, импортируйте sys и выполните sys.path.insert(0, '/path/to/datetime')замену этого пути путем к любому каталогу, который вы только что создали. Теперь попробуйте что-то вроде from datetime import datetime;datetime.now(). Вы должны получить AttributeError (потому что он импортирует ваш пустой файл сейчас). Если вы повторите эти шаги без создания пустого файла инициализации, этого не произойдет. Это то, что он призван предотвратить.
Двухразрядный алхимик
4
@ DarekNędza У вас что-то настроено неправильно, если вы не можете просто открыть интерпретатор Python и выполнить from datetime import datetimeошибку без ошибок. Это хорошо, вплоть до версии 2.3!
Названные __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__.pyтребовался в Python 2.X и все еще требуется в Python 2.7.12 (я проверял его), но он больше не требуется (предположительно) начиная с Python 3.3 и далее, и не требуется в Python 3.4.3 (I проверил это). См. Stackoverflow.com/questions/37139786 для получения дополнительной информации.
Rob_before_edits
4
Не используйте это. Это пакет "namespace", а не обычный пакет. Пакет namespace используется в очень редких случаях. Возможно, вам не нужно знать, когда его использовать. Просто используйте __init__.py.
метан
2
Однако, если у вас есть setup.pyи вы используете, find_packages()необходимо иметь __init__.pyв каждом каталоге. См stackoverflow.com/a/56277323/7127824
techkuz
484
В дополнение к маркировке каталога как пакета Python и определению __all__, __init__.pyпозволяет определить любую переменную на уровне пакета. Это часто удобно, если пакет определяет что-то, что будет часто импортироваться, в стиле API. Эта модель способствует приверженности питонской философии «квартира лучше вложенного».
Пример
Вот пример из одного из моих проектов, в котором я часто импортирую sessionmakerвызываемый Sessionдля взаимодействия с моей базой данных. Я написал пакет базы данных с несколькими модулями:
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 importSession
session =Session()
Конечно, это небольшое удобство - альтернативой будет определение Sessionв новом файле, например, «create_session.py» в моем пакете базы данных, и запуск новых сеансов с использованием:
from database.create_session importSession
session =Session()
дальнейшее чтение
Существует довольно интересный поток reddit, охватывающий подходящее использование __init__.pyздесь:
engine, sessionmaker, create_engine, И osвсе это может также быть импортировано из database... похоже , как ты напутал это пространство имен.
ArtOfWarfare
9
@ArtOfWarfare, вы можете использовать __all__ = [...]для ограничения импорта import *. Но кроме этого, да, у вас осталось грязное пространство имен верхнего уровня.
Натан Гулд
Могу ли я узнать, что такое «URL базы данных»? Я попытался повторить это, заключив create_engine в «mysql + mysqldb: // root: python @ localhost: 3306 / test», но это не работает. Спасибо.
SunnyBoiz
2
Как бы вы получили доступ к классу 'Session', определенному в init, изнутри пакета, например, quieries.py?
vldbnc
253
Есть 2 основные причины __init__.py
Для удобства: другим пользователям не нужно будет знать точное местоположение ваших функций в иерархии вашего пакета.
о, прежде чем прочитать ваш ответ, я подумал, что вызов функции явно из ее местоположения - хорошая практика.
Аэрин
2
@ Аэрин было бы лучше не считать короткие утверждения (или, в данном случае, субъективные выводы) всегда верными. Импорт из __init__.pyможет быть полезным иногда, но не всегда.
Тобиас Сетте
2
Этот код выполняется во время импорта или во время выполнения?
user1559897
111
__init__.pyФайл делает Python лечить каталоги , содержащие его в качестве модулей.
Кроме того, это первый файл, который будет загружен в модуль, поэтому вы можете использовать его для выполнения кода, который вы хотите запускать каждый раз при загрузке модуля, или указывать субмодули для экспорта.
Встроенная поддержка каталогов пакетов, которые не требуют __init__.pyфайлов маркеров и могут автоматически охватывать несколько сегментов пути (вдохновленные различными сторонними подходами к пакетам пространств имен, как описано в PEP 420 )
В Python определение пакета очень просто. Как и в Java, иерархическая структура и структура каталогов одинаковы. Но вы должны иметь __init__.pyв упаковке. Я объясню __init__.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содержимого.
Как будет выглядеть мой setup.py для того же импорта через упакованную библиотеку? from package_x.subPackage_b.module_n1 import function_X
Technazi
поэтому ключевой момент здесь - это «использование * импорта, пакет модуля зависит от содержимого init .py»
Минни
54
Хотя 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пакета ( см. Здесь структуру файла пакета ):
Это облегчает импорт других файлов Python. Когда вы помещаете этот файл в каталог (скажем, вещи), содержащий другие файлы py, вы можете сделать что-то вроде import stuff.other.
root\
stuff\
other.py
morestuff\
another.py
Без этого __init__.pyвнутри каталога вы не смогли бы импортировать other.py, потому что Python не знает, где находится исходный код материала, и не может распознать его как пакет.
У меня есть та же структура в моем проекте (Python 3.4), но я не могу заставить другой файл увидеть другой файл. Как мне сделать импорт? из root.stuff импортировать другие? Он работает в режиме отладки VSCode, но не в командной строке. Любые идеи?
Родригор
10
__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
что вы имеете в виду " функция a () может быть импортирована из файла b.py [snippet] Без нее, однако, вы не можете импортировать напрямую. "? Я могу импортировать функцию a () из файла b.py без __init__.py.
Ответы:
Раньше он был обязательной частью пакета ( старый, до 3.3 «обычный пакет» , а не более новый 3.3+ «пакет пространства имен» ).
Вот документация.
Но просто нажмите на ссылку, она содержит пример, дополнительную информацию и объяснение пакетов пространства имен, типа пакетов без
__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
находится на вашем пути, вы можете импортировать код вmodule.py
видеили
Если вы удалите
__init__.py
файл, Python больше не будет искать подмодули внутри этого каталога, поэтому попытки импортировать модуль потерпят неудачу.__init__.py
Файл обычно пустой, но может быть использован для экспорта отдельных частей пакета под более удобным названием, трюмные удобные функции и т.д. Учитывая приведенную выше пример, содержимое модуля инициализации можно обращаться какосновываясь на этом
источник
__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
для взаимодействия с моей базой данных. Я написал пакет базы данных с несколькими модулями:My
__init__.py
содержит следующий код:Так как я определил
Session
здесь, я могу начать новый сеанс, используя синтаксис ниже. Этот код будет одинаково выполняться изнутри или снаружи каталога пакета «database».Конечно, это небольшое удобство - альтернативой будет определение
Session
в новом файле, например, «create_session.py» в моем пакете базы данных, и запуск новых сеансов с использованием:дальнейшее чтение
Существует довольно интересный поток 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
Для удобства: другим пользователям не нужно будет знать точное местоположение ваших функций в иерархии вашего пакета.
тогда другие могут вызвать add ()
не зная file1, вроде
Если вы хотите что-то инициализировать; например, ведение журнала (который следует поместить на верхний уровень):
источник
__init__.py
может быть полезным иногда, но не всегда.__init__.py
Файл делает Python лечить каталоги , содержащие его в качестве модулей.Кроме того, это первый файл, который будет загружен в модуль, поэтому вы можете использовать его для выполнения кода, который вы хотите запускать каждый раз при загрузке модуля, или указывать субмодули для экспорта.
источник
Начиная с Python 3.3,
__init__.py
больше не требуется определять каталоги как импортируемые пакеты Python.Проверьте PEP 420: неявные пакеты пространства имен :
Вот тест:
ссылки:
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
файл с примером ниже:__init__.py
может быть пустым, пока оно существует. Это указывает на то, что каталог следует рассматривать как пакет. Конечно,__init__.py
также можно установить соответствующий контент.Если мы добавим функцию в module_n1:
После запуска:
Затем мы последовали за пакетом иерархии и назвали module_n1 функцией. Мы можем использовать
__init__.py
в subPackage_b следующим образом:После запуска:
Следовательно, используя * import, модуль пакета зависит от
__init__.py
содержимого.источник
from package_x.subPackage_b.module_n1 import function_X
Хотя Python работает без
__init__.py
файла, вы все равно должны включить его.Он указывает, что пакет должен рассматриваться как модуль, поэтому включайте его (даже если он пуст).
Существует также случай, когда вы можете использовать
__init__.py
файл:Представьте, что у вас была следующая файловая структура:
И
methods.py
содержал это:Для использования
foo()
вам понадобится одно из следующих:Может быть, вам нужно (или вы хотите) хранить
methods.py
внутриmain_methods
(например, время выполнения / зависимости), но вы хотите только импортироватьmain_methods
.Если вы изменили имя
methods.py
на,__init__.py
то вы можете использоватьfoo()
, просто импортировавmain_methods
:Это работает, потому что
__init__.py
рассматривается как часть пакета.Некоторые пакеты Python действительно делают это. Примером является JSON , где во время выполнения
import json
фактически импортируется__init__.py
изjson
пакета ( см. Здесь структуру файла пакета ):источник
__init__.py
будет рассматривать каталог, в котором он находится, как загружаемый модуль.Для людей, которые предпочитают читать код, я разместил здесь комментарий Двухбитного Алхимика .
источник
Это облегчает импорт других файлов Python. Когда вы помещаете этот файл в каталог (скажем, вещи), содержащий другие файлы py, вы можете сделать что-то вроде import stuff.other.
Без этого
__init__.py
внутри каталога вы не смогли бы импортировать other.py, потому что Python не знает, где находится исходный код материала, и не может распознать его как пакет.источник
__init__.py
Файл делает импорт легко. Когда__init__.py
в пакете присутствует an , функциюa()
можно импортировать из файлаb.py
следующим образом:Без этого, однако, вы не можете импортировать напрямую. Вы должны изменить системный путь:
источник