Импорт из родственного каталога

У меня есть класс Python под названием «ClassA» и другой класс Python, который должен импортировать ClassA, который является «ClassB». Структура каталогов следующая:

MainDir
../Dir
..../DirA/ClassA
..../DirB/ClassB

Как мне использовать sys.path, чтобы ClassB мог использовать ClassA?


person skylerl    schedule 27.12.2010    source источник
comment
Это называется относительным импортом и содержит довольно много материала для Google и вопросов SO.   -  person    schedule 28.12.2010
comment
stackoverflow.com/questions/279237 /   -  person jgritty    schedule 28.12.2010


Ответы (3)


Вы действительно должны использовать пакеты. Затем MainDir помещается в точку файловой системы на sys.path (например, .../site-packages), тогда вы можете сказать в ClassB:

from MainDir.Dir.DirA import ClassA # which is actually a module

Вам просто нужно поместить файлы с именем __init__.py в каждый каталог, чтобы сделать его иерархией пакетов.

person Keith    schedule 27.12.2010
comment
Я добавил MainDir в sys.path и попробовал ваше решение, но оно просто говорит, что нет модуля с именем MainDir.Dir.DirA, и во всех каталогах есть init.pys. - person skylerl; 28.12.2010
comment
Не добавляйте MainDir, добавьте его родительский каталог. Если вы добавите MainDir (если это не корень пакета, это нормально), то вместо этого импортируйте как from Dir.DirA import ClassA. - person Keith; 28.12.2010
comment
Мне потребовалось некоторое время, чтобы понять, что превращение вашего кода в пакет означает все 1) размещение __init__.py в верхнем каталоге вашего кода и 2) добавление родительского каталог верхнего каталога на ваш PYTHONPATH и 3) установить переменную __package__ в вашей программе Python на имя каталога, который содержит __init__.py. Теперь все работает, спасибо! - person AstroFloyd; 20.05.2021

как буквальный ответ на вопрос 'Импорт Python из родительского каталога':

чтобы импортировать «mymodule», который находится в родительском каталоге вашего текущего модуля:

import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0,parentdir) 
import mymodule

изменить К сожалению, атрибут __file__ не всегда установлен. Более безопасный способ получить родительский каталог — через модуль проверки:

import inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
person Remi    schedule 21.03.2012
comment
Реми - Спасибо за буквальный ответ. Я нашел это полезным при написании тестового кода для приложения Python. Я могу поместить тестовый код в подкаталог и начать размещать тесты без изменения существующего проекта. (Другими словами, преобразование существующего кода в модуль до проведения тестов было бы неправильным порядком действий с точки зрения управления риском появления ошибок в рабочем коде.) Ваш метод изменения пути к модулю удобен. - person Heath Hunnicutt; 21.07.2013

Вы можете использовать относительный импорт (пример из ссылки, текущий модуль - A.B.C) :

from . import D                 # Imports A.B.D
from .. import E                # Imports A.E
from ..F import G               # Imports A.F.G
person crazylammer    schedule 27.12.2010
comment
@Yakattak: Да, но они все равно должны быть в упаковке;) - person ; 28.12.2010
comment
это выглядит как лучший и самый простой ответ - person Rabih Kodeih; 20.09.2012
comment
Предостережение: относительный импорт зависит от __name__ модулей, поэтому, если вы когда-либо намереваетесь запустить текущий модуль (который устанавливает __name__ в __main__), относительный импорт завершится ошибкой. - person Yibo Yang; 29.04.2017
comment
Каковы критерии для того, чтобы назвать это пакетом? Только то, что каждая из подпапок содержит файл init.py? - person Sledge; 07.08.2019
comment
@Sledge Это означает все три из 1) размещение __init__.py в верхнем каталоге вашего кода и 2) добавление родительского каталога верхнего каталога в ваш PYTHONPATH и 3) установка переменной __package__ в вашей программе Python на имя каталога, содержащего __init__.py. - person AstroFloyd; 20.05.2021