Использовать случаи для __init__.py в python 3.3+

Теперь, когда __init__.py больше не требуется, чтобы сделать каталог признанным пакетом, лучше всего избегать их, если возможное? Или есть еще хорошо принятые варианты использования для __init__.py в python 3.3 +?

Из того, что я понимаю, __init__.py были очень часто использованы для запуска кода во время импорта модуля (например для инкапсуляции внутренней файловой структуры пакета или для выполнения некоторые шаги инициализации). Являются ли эти примеры использования релевантными для python 3.3 +?

Ответ 1

Там очень хорошее обсуждение этого вопроса в этом ответе, и вы, вероятно, должны быть знакомы с PEP 420, чтобы уточнить разницу между регулярными пакетами (используйте __init__.py) и пакеты пространства имен (не).

Что я предлагаю в качестве ответа, это сочетание чтения, ссылок и мнения. Никаких претензий к тому, чтобы быть "каноническим" или "питоническим" здесь.

Используются ли [инициализации] случаи использования, все еще имеющие отношение к python 3.3 +?

Да. Возьмите пример в качестве варианта использования, когда автор пакета хочет внести несколько вещей в пространство имен корневых пакетов, чтобы пользователь не должен был заботиться о своей внутренней структуре.

Другим примером является создание иерархии модулей. Эта ссылка (O'Reilly) фактически говорит:

Цель файлов __init__.py состоит в том, чтобы включить дополнительный код инициализации, который выполняется с разными уровнями пакета.

Они рассматривают пакеты пространства имен в этом обсуждении, но продолжают:

При прочих равных условиях, включите файлы __init__.py, если вы только начинаете с создания нового пакета.

Итак, для вашего второго вопроса

лучше всего избегать __init__.py, если это возможно?

Нет, если вы не намерены создавать пакет пространства имен, а не обычный пакет, и в этом случае вы не должны использовать __init__.py.

Зачем вам это нужно? Ссылка O'Reilly имеет самый ясный пример Я видел, почему пакеты пространства имен классные, что позволяет свернуть пространства имен от отдельных, независимо поддерживаемые пакеты:

foo-package/
    spam/
        blah.py

bar-package/
    spam/
        grok.py

Что позволяет

>>> import sys
>>> sys.path.extend(['foo-package', 'bar-package'])
>>> import spam.blah
>>> import spam.grok
>>>

Таким образом, каждый может расширить пространство имен своим собственным кодом. Круто.