Правильный способ "Абсолютный импорт" в Python 2.7
- Python 2.7.10
- В virtualenv
- Включить
from __future__ import absolute_import
в каждом модуле
Дерево каталогов выглядит следующим образом:
Project/
prjt/
__init__.py
pkg1/
__init__.py
module1.py
tests/
__init__.py
test_module1.py
pkg2/
__init__.py
module2.py
tests/
__init__.py
test_module2.py
pkg3/
__init__.py
module3.py
tests/
__init__.py
test_module3.py
data/
log/
Я попытался использовать функцию compute()
pkg2/module2.py
в pkg1/module1.py
, написав как:
# In module1.py
import sys
sys.path.append('/path/to/Project/prjt')
from prjt.pkg2.module2 import compute
Но когда я запустил python module1.py
, интерпретатор поднял значение ImportError, которое No module named prjt.pkg2.module2
.
- Каков правильный способ "абсолютного импорта"? Должен ли я добавить путь к
Project
в sys.path
?
- Как я могу запустить
test_module1.py
в интерактивном интерпретаторе? Под python prjt/pkg1/tests/test_module1.py
или python -m prjt/pkg1/tests/test_module1.py
?
Ответы
Ответ 1
Как найти модуль python
python найдет модуль из sys.path
, а первая запись sys.path[0]
is '' означает, что python найдет модуль из текущего рабочего каталога
import sys
print sys.path
и python найти сторонний модуль от site-packages
поэтому для абсолютного импорта вы можете
добавьте свой пакет к sys.path
import sys
sys.path.append('the_folder_of_your_package')
import module_you_created
module_you_created.fun()
экспорт PYTHONPATH
PYTHONPATH будет импортирован в sys.path перед выполнением
export PYTHONPATH=the_folder_of_your_package
import sys
[p for p in sys.path if 'the_folder_of_your_package' in p]
Как я могу запустить test_module1.py в интерактивном интерпретаторе? С помощью python Project/pkg1/tests/test_module1.py или python -m Project/pkg1/tests/test_module1.py?
вы можете использовать if __name__ == '__main__':
идиоматический путь и использовать python Project/pkg1/tests/test_module1.py
if __name__ = '__main__':
main()
Ответ 2
Если вы добавляете sys.path.append('path/to/Project')
в prjt/__init__.py
, вам необходимо импортировать подмодули так: from pkg2.module2 import compute
(без спецификации prjt
), поскольку prjt
импорт пакета prjt
и папка более высокого уровня не находится в sys.path
. Это именно то, что предложил @Cissoid.
Кстати, from __future__ import absolute_import
не нужен для Py> = 3.0.
Отвечая на ваш второй вопрос... У меня очень похожая структура для подпапки unittests, поэтому в pkg/unittests/testall.py
я написал следующее:
testfolder = os.path.abspath(os.path.dirname(__file__))
project_root = os.path.abspath(os.path.join(testfolder, r"..\.."))
sys.path.append(project_root)
import pkg
Я запускаю его без -m
потому что это ненужное осложнение.
Ответ 3
Импортировать внешний путь проекта.
sys.path.append('/path/to/Project')
Или импортировать "вычислить" начало из pkg2
from pkg2.module2 import compute
Ответ 4
попробуйте это
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
Это даст абсолютный путь
Ответ 5
Используя явный относительный импорт, это должно работать из module1.py
:
from ..pkg2.module2 import compute()
Это чище, чем возиться с PYTHONPATH
...