Вопрос-Ответ

Importing modules from parent folder

Импорт модулей из родительской папки

Я использую Python 2.5.

Это мое дерево папок:

ptdraft/
nib.py
simulations/
life/
life.py

(У меня также есть __init__.py в каждой папке, опущен здесь для удобства чтения)

Как мне импортировать nib модуль изнутри life модуля? Я надеюсь, что это можно сделать, не возясь с sys.path.

Примечание: Основной запускаемый модуль находится в ptdraft папке.

Переведено автоматически
Ответ 1

Вы могли бы использовать относительный импорт (Python >= 2.5):

from ... import nib

(Что нового в Python 2.5) PEP 328: абсолютный и относительный импорт

Ответ 2

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

Решение без sys.path взломов

Краткие сведения


  • Перенесите код в одну папку (например, packaged_stuff)

  • Создайте pyproject.toml (более старую альтернативу: setup.py)

  • Pip установит пакет в редактируемом состоянии с помощью pip install -e <myproject_folder>

  • Импорт с помощью from packaged_stuff.modulename import function_name

Настройка

Я предполагаю ту же структуру папок, что и в вопросе

.
└── ptdraft
├── __init__.py
├── nib.py
└── simulations
├── __init__.py
└── life
├── __init__.py
└── life.py

Я вызываю . корневую папку, и в моем случае она находится в C:\tmp\test_imports.

Шаги


1) Add a pyproject.toml to the root folder

The contents of the pyproject.toml can be simply

[project]
name = "ptdraft"
version = "0.1.0"
description = "My small project"

[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.2,<4"]

Basically "any" valid pyproject.toml would work. This is just a minimal working example, which uses flit as build backend.


2) Use a virtual environment

Если вы знакомы с виртуальными средами, активируйте одну из них и переходите к следующему шагу. Использование виртуальных сред не абсолютно обязательно, но они действительно помогут вам в долгосрочной перспективе (когда у вас выполняется более 1 проекта ..). Самые простые шаги (запускаются в корневой папке)


  • Создание виртуального env

    • python -m venv venv



  • Активировать виртуальный env

    • . venv/bin/activate (Linux) или ./venv/Scripts/activate (Win)



  • Деактивировать виртуальную среду env

    • deactivate (Linux)



Чтобы узнать больше об этом, просто найдите в Google "python virtualenv tutorial" или аналогичный. Вам, вероятно, никогда не понадобятся никакие другие команды, кроме создания, активации и деактивации.

После создания и активации виртуальной среды в вашей консоли должно быть указано имя виртуальной среды в круглых скобках

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) pip установит ваш проект в редактируемом состоянии

Установите свой пакет верхнего уровня (здесь ptdraft) с помощью pip. Хитрость заключается в использовании -e флага при выполнении установки. Таким образом, он устанавливается в состоянии, доступном для редактирования, и все изменения, внесенные в файлы .py, будут автоматически включены в установленный пакет. Обратите внимание, что для -e флага в pyproject.toml требуется pip 21.3 или новее.

В корневом каталоге запустите

pip install -e . (обратите внимание на точку, она обозначает "текущий каталог")

Вы также можете увидеть, что он установлен с помощью pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///home/user/projects/ptdraft
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Preparing editable metadata (pyproject.toml) ... done
....
Successfully built ptdraft
Installing collected packages: ptdraft
Successfully installed ptdraft-0.1.0
(venv) PS C:\tmp\test_imports> pip freeze
ptdraft==0.1.0

4) Импортируйте, добавляя mainfolder к каждому импорту

В этом примере mainfolder будет ptdraft. Преимущество этого в том, что вы не столкнетесь с конфликтами имен с именами других модулей (из стандартной библиотеки python или модулей сторонних производителей).


Пример использования

nib.py

def function_from_nib():
print('I am the return value from function_from_nib!')

life.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
function_from_nib()

Выполняется life.py

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
Ответ 3

Относительный импорт (как в from .. import mymodule) работает только в пакете. Чтобы импортировать 'mymodule', который находится в родительском каталоге вашего текущего модуля:

import os
import sys
import inspect

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)

import mymodule

Примечание: __file__ Атрибут задается не всегда. Вместо использования os.path.abspath(__file__) я предлагаю использовать модуль inspect для получения имени файла (и пути) текущего файла.

Ответ 4

Похоже, проблема не связана с тем, что модуль находится в родительском каталоге или что-то в этом роде.

Вам нужно добавить каталог, который содержит ptdraft в PYTHONPATH

Вы сказали, что это import nib сработало с вами, это, вероятно, означает, что вы добавили ptdraft сам (не родительский) PYTHONPATH .

python