Если бы вы могли привести несколько примеров, я был бы очень доволен.
Ответ 2
Все, что я хочу знать, это то, что именно означает __package__
Это механизм, который разрешает явный относительный импорт.
Существует три возможных категории значений для __package__
- Имя пакета (строка)
- Пустая строка
- Без
Название пакета
То есть, если модуль находится в пакете, для __package__
задается имя пакета, чтобы разрешить явный относительный импорт. частности:
Когда модуль представляет собой пакет, его значение __package__
должно быть установлено равным __name__
. Если модуль не является пакетом, для субмодулей __package__
следует установить [...] имя родительского пакета.
Пустая строка
Если модуль находится в корневом или верхнем уровне, то есть текущий модуль импортируется с помощью
import current_module
или когда модуль верхнего уровня запускается как точка входа, например:
$ python -m current_module
затем __package__
- пустая строка. Или, как сказано в документации:
Когда модуль не является пакетом, для модулей верхнего уровня __package__
следует установить пустую строку...
Без
Если модуль/скрипт запускается по имени файла, __package__
- Нет:
Если основной модуль указан в имени файла, для атрибута __package__
будет установлено значение Нет.
Доказательства
Во-первых, давайте создадим файловую структуру с шумной отладкой - используя Python 3.6:
text = "print(f'{__name__}, __file__: {__file__}, __package__: {repr(__package__)}')"
from pathlib import Path
Path('foo.py').write_text(text)
Path('package').mkdir()
Path('package/__init__.py').write_text(text)
Path('package/__main__.py').write_text(text)
Path('package/bar.py').write_text(text)
# and include a submodule with a relative import:
Path('package/baz.py').write_text(text + '\nfrom . import bar')
Теперь мы видим, что foo.py, выполняемый как модуль, имеет пустую строку для __package__
, тогда как скрипт, выполняемый по имени файла в качестве точки входа, имеет None
:
$ python -m foo
__main__, __file__: ~\foo.py, __package__: ''
$ python foo.py
__main__, __file__: foo.py, __package__: None
Когда мы выполняем пакет как модуль для точки входа, запускается его модуль __init__.py
, затем запускается его __main__.py
:
$ python -m package
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\__main__.py, __package__: 'package'
Аналогичным образом, когда мы выполняем подмодуль в качестве модуля для точки входа, модуль __init__.py
запускается, а затем запускается:
$ python -m package.bar
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\bar.py, __package__: 'package'
Наконец, мы видим, что явный относительный импорт, вся причина наличия __package__
(что здесь происходит в последнюю очередь), включен:
$ python -m package.baz
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\baz.py, __package__: 'package'
package.bar, __file__: ~\package\bar.py, __package__: 'package'
Обратите внимание, что в выводе я заменил ~
на родительские каталоги.