Вопрос

Что такое __init__.py для в исходном каталоге Python?

Это было полезно?

Решение

Раньше он был обязательной частью пакета ( старый, предварительно -3.3 & Quot; обычный пакет & Quot; , а не более новый 3.3+ " пакет пространства имен " ).

Вот документация.

  

Python определяет два типа пакетов: обычные пакеты и пакеты пространства имен. Обычные пакеты - это традиционные пакеты, которые существовали в Python 3.2 и более ранних версиях. Обычный пакет обычно реализуется как каталог, содержащий файл __init__.py. Когда обычный пакет импортируется, этот файл <=> выполняется неявно, и определяемые им объекты привязываются к именам в пространстве имен пакета & # 8217; s. Файл <=> может содержать тот же код Python, что и любой другой модуль, и Python добавит некоторые дополнительные атрибуты в модуль при его импорте.

Но просто нажмите на ссылку, она содержит пример, дополнительную информацию и объяснение пакетов пространства имен, типа пакетов без <=>.

Другие советы

Файлы с именем __init__.py используются для пометки каталогов на диске как каталогов пакетов Python. Если у вас есть файлы

mydir/spam/__init__.py
mydir/spam/module.py

и mydir на вашем пути, вы можете импортировать код в module.py как

import spam.module

или

from spam import module

Если вы удалите файл <=>, Python больше не будет искать подмодули внутри этого каталога, поэтому попытки импорта модуля завершатся неудачей.

Файл <=> обычно пуст, но его можно использовать для экспорта выбранных частей пакета под более удобным именем, хранения вспомогательных функций и т. д. Учитывая приведенный выше пример, доступ к содержимому модуля init можно получить как

import spam

на основе этой

В дополнение к маркировке каталога как пакета Python и определению __all__ __init__.py позволяет определить любую переменную на уровне пакета. Это часто удобно, если пакет что-то определяет это будет импортироваться часто, в стиле API. Этот шаблон способствует соблюдению Pythonic &; Квартира лучше, чем вложенная & Quot; философии.

Пример

Вот пример из одного из моих проектов, в котором я часто импортирую sessionmaker с именем Session для взаимодействия с моей базой данных. Я написал & Quot; database & Quot; пакет с несколькими модулями:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

My <=> содержит следующий код:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Поскольку я определяю здесь <=>, я могу начать новый сеанс, используя приведенный ниже синтаксис. Этот код будет выполнен одинаково внутри или снаружи & Quot; database & Quot; каталог пакетов.

from database import Session
session = Session()

Конечно, это небольшое удобство - альтернативой может быть определение <=> в новом файле, например " create_session.py " в моем пакете базы данных и начинайте новые сеансы, используя:

from database.create_session import Session
session = Session()

Дальнейшее чтение

Здесь есть довольно интересная ветка reddit, в которой рассказывается о соответствующих случаях использования <=>:

http://www.reddit.com/r/Python/comments/1bbbwk/whin____inin_y_

По мнению большинства, <=> файлы должны быть очень тонкими, чтобы не нарушать &; явное лучше, чем неявное " философии.

Существует две основные причины __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.

    Проверить БОДРОСТЬ ДУХА 420:Неявные пакеты пространства имен:

    Встроенная поддержка каталогов пакетов, которые не требуют __init__.py маркерные файлы и могут автоматически охватывать несколько сегментов пути (вдохновленные различными сторонними подходами к пакетам пространств имен, как описано в БОДРОСТЬ ДУХА 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/
    __init__.py Не требуется для пакетов в python 3?

    В Python определение пакета очень просто. Как и в Java, иерархическая структура и структура каталогов одинаковы. Но вы должны иметь __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
    

    <=> может быть пустым, если он существует. Это указывает на то, что каталог следует рассматривать как пакет. Конечно, <=> также может установить соответствующий контент.

    Если мы добавим функцию в 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 функцию. Мы можем использовать <=> в 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, пакет модуля зависит от содержания <=>.

    Несмотря на то, что Python работает без файла __init__.py, вы все равно должны включить его.

    Он указывает, что пакет должен рассматриваться как модуль, поэтому включите его (даже если он пуст).

    В некоторых случаях вы можете использовать methods.py файл:

    Представьте, что у вас была следующая файловая структура:

    main_methods 
        |- methods.py
    

    И foo() содержал это:

    def foo():
        return 'foo'
    

    Для использования main_methods вам понадобится одно из следующих действий:

    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()
    

    Возможно, вам нужно (или вы хотите) сохранить import json внутри json (например, среды выполнения / зависимости), но вы хотите импортировать только Lib/json/__init__.py.

    <Ч>

    Если вы изменили имя <=> на <=>, вы можете использовать <=>, просто импортировав <=>:

    import main_methods
    print(main_methods.foo()) # Prints 'foo'
    

    Это работает, потому что <=> рассматривается как часть пакета.

    <Ч>

    Некоторые пакеты Python действительно делают это. Примером может служить JSON , где при запуске <=> фактически импортируется <=> из пакета <=> ( см. здесь структуру файла пакета ):

      

    Исходный код: <=>

    __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 упрощает импорт. Когда в пакете присутствует a(), функцию b.py можно импортировать из файла <=> следующим образом:

    from b import a
    

    Без этого вы не можете импортировать напрямую. Вы должны изменить системный путь:

    import sys
    sys.path.insert(0, 'path/to/b.py')
    
    from b import a
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top