Я полагаю, что файл *.pth
в каталоге site-packages
(скорее всего, файл easy-install.pth
) влияет на значение sys.path
. Этот эффект не зависит от текущего рабочего каталога. Я до сих пор не совсем уверен, какую именно роль играет файл *.egg-link
в каталоге site-packages
(хотя он действительно подразумевается, по крайней мере частично, как независимая от платформы замена символических ссылок).
Что касается пакетов пространства имен ... Давайте рассмотрим следующее дерево каталогов:
.
├── alfa
│ ├── bravo
│ │ ├── one.py
│ │ └── zero.py
│ └── zero.py
├── foo
│ ├── bar
│ │ ├── two.py
│ │ └── zero.py
│ └── zero.py
└── src
├── alfa
│ ├── bravo
│ │ ├── three.py
│ │ └── zero.py
│ └── zero.py
└── foo
├── bar
│ ├── four.py
│ └── zero.py
├── __init__.py
└── zero.py
Все *.py
файлы содержат следующее:
print(__name__, __file__)
Обратите внимание, как это существует только один инициализатор пакета src/foo/__init__.py
.
Модули alfa.bravo.one
и foo.bar.two
импортируются, поскольку текущий каталог всегда находится в пути поиска интерпретатора Python (sys.path
):
$ python3 -c 'import alfa.bravo.one'
alfa.bravo.one /home/sinoroc/workspace/so-59682278/alfa/bravo/one.py
$ python3 -c 'import foo.bar.two'
foo.bar.two /home/sinoroc/workspace/so-59682278/foo/bar/two.py
Но импорт alfa.bravo.three
и foo.bar.four
невозможен:
$ python3 -c 'import alfa.bravo.three'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'alfa.bravo.three'
$ python3 -c 'import foo.bar.four'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'foo.bar.four'
Это так, потому что они находятся в каталоге src
, а этот каталог не в Python ' s путь :
$ python3 -c 'import sys; print(sys.path)'
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/sinoroc/workspace/so-59682278/.venv/lib/python3.6/site-packages']
Каталог можно добавить к пути Python, записав его местоположение в .pth
в каталоге site-packages
интерпретатора:
$ echo "${PWD}/src" > '.venv/lib/python3.6/site-packages/test.pth'
$ python3 -c 'import sys; print(sys.path)'
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/sinoroc/workspace/so-59682278/.venv/lib/python3.6/site-packages', '/home/sinoroc/workspace/so-59682278/src']
А теперь можно импортировать alfa.bravo.three
и foo.bar.four
:
$ python3 -c 'import alfa.bravo.three'
alfa.bravo.three /home/sinoroc/workspace/so-59682278/src/alfa/bravo/three.py
$ python3 -c 'import foo.bar.four'
foo /home/sinoroc/workspace/so-59682278/src/foo/__init__.py
foo.bar.four /home/sinoroc/workspace/so-59682278/src/foo/bar/four.py
Модуль alfa.bravo.one
по-прежнему можно импортировать благодаря пакетам пространства имен:
$ python3 -c 'import alfa.bravo.one'
alfa.bravo.one /home/sinoroc/workspace/so-59682278/alfa/bravo/one.py
Но поскольку пакет foo
из каталога src
имеет инициализатор, foo
не является пакетом пространства имен больше и модуль foo.bar.two
не может быть импортирован:
$ python3 -c 'import foo.bar.two'
foo /home/sinoroc/workspace/so-59682278/src/foo/__init__.py
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'foo.bar.two'
Теперь для модулей zero
это немного удивительнее. В текущем каталоге и в каталоге src
есть модули с точно таким же путем импорта:
$ python3 -c 'import alfa.zero'
alfa.zero /home/sinoroc/workspace/so-59682278/alfa/zero.py
$ python3 -c 'import alfa.bravo.zero'
alfa.bravo.zero /home/sinoroc/workspace/so-59682278/alfa/bravo/zero.py
$ python3 -c 'import foo.zero'
foo /home/sinoroc/workspace/so-59682278/src/foo/__init__.py
foo.zero /home/sinoroc/workspace/so-59682278/src/foo/zero.py
$ python3 -c 'import foo.bar.zero'
foo /home/sinoroc/workspace/so-59682278/src/foo/__init__.py
foo.bar.zero /home/sinoroc/workspace/so-59682278/src/foo/bar/zero.py
Если инициализированный пакет отсутствует (alfa
), то версия в текущей рабочей каталог импортируется. Но если существует одна версия с инициализатором (foo
), то это версия импортируемого инициализированного пакета.
Примечания