Подтвердить что ты не робот

Правильный способ "Абсолютный импорт" в 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?
4b9b3361

Ответ 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...