Я хочу наследовать от класса в файле, который находится в каталоге выше текущего.
Можно ли относительно импортировать этот файл?
источник
Я хочу наследовать от класса в файле, который находится в каталоге выше текущего.
Можно ли относительно импортировать этот файл?
from ..subpkg2 import mod
Согласно документации по Python: внутри иерархии пакетов используйте две точки, как сказано в документе import import :
При указании модуля для импорта не нужно указывать абсолютное имя модуля. Когда модуль или пакет содержится в другом пакете, можно сделать относительный импорт в том же самом верхнем пакете, не упоминая имя пакета. Используя начальные точки в указанном модуле или пакете после,
from
вы можете указать, как высоко пройти по текущей иерархии пакетов без указания точных имен. Одна начальная точка означает текущий пакет, в котором существует модуль, выполняющий импорт. Две точки означают один уровень пакета . Три точки выше двух уровней и т. Д. Итак, если вы выполняетеfrom . import mod
из модуля вpkg
пакете, то в итоге вы импортируетеpkg.mod
. Если вы выполните . Спецификация для относительного импорта содержится вfrom ..subpkg2 import mod
изнутри,pkg.subpkg1
вы будете импортироватьpkg.subpkg2.mod
PEP 328 .
PEP 328 имеет дело с абсолютным / относительным импортом.
источник
Ответ @ gimel верен, если вы можете гарантировать иерархию пакетов, о которой он говорит. Если вы не можете - если ваша реальная потребность в том виде, в каком вы ее выразили, привязана исключительно к каталогам и не имеет никакого отношения к упаковке - тогда вам нужно поработать,
__file__
чтобы выяснить родительский каталог (os.path.dirname
подойдет пара вызовов; -), затем (если этот каталог еще неsys.path
включен) prepend временно вставляет указанный dir в самом началеsys.path
,__import__
снова удаляет указанный dir - грязная работа действительно, но, «когда вы должны, вы должны» (и Pyhon стремится никогда не мешайте программисту делать то, что должно быть сделано - как сказано в стандарте ISO C в разделе «Дух C» в предисловии! -).Вот пример, который может работать для вас:
источник
sys.path
сделать один и тот же модуль доступным под разными именами и всеми соответствующими ошибками. autopath.py в pypy или _preamble.py в витой решают ее, используя критерии поиска, которые определяют пакет верхнего уровня при обходе каталогов вверх.sys.path.remove(pathYouJustAdded)
после импорта, которое вам нужно, чтобы не сохранять этот новый путь.Импортировать модуль из каталога, который находится ровно на один уровень выше текущего каталога:
источник
from .. import module
Я получил ошибку ValueError: Попытка относительного импорта в не-пакет , следуя рекомендацииКак загрузить модуль, который является каталогом
Предисловие: я существенно переписал предыдущий ответ, надеясь помочь облегчить людям доступ к экосистеме python и, надеюсь, дать каждому наилучшее изменение успеха с помощью системы импорта python.
Это покроет относительный импорт в пакете , что, я думаю, является наиболее вероятным случаем вопроса ОП.
Python - это модульная система
Вот почему мы пишем
import foo
для загрузки модуля «foo» из корневого пространства имен, вместо того, чтобы писать:Python не связан с файловой системой
Вот почему мы можем встроить python в среду, в которой нет файловой системы defacto без предоставления виртуальной, например, Jython.
Благодаря отделению от файловой системы импорт может быть гибким, этот дизайн позволяет выполнять такие вещи, как импорт из архивных / zip-файлов, импорт одиночных файлов, кэширование байт-кода, расширения cffi, даже удаленная загрузка определения кода.
Так что, если импорт не связан с файловой системой, что означает «один каталог вверх»? Мы должны выбрать некоторую эвристику, но мы можем сделать это, например, при работе в пакете , уже была определена некоторая эвристика, которая делает относительный импорт похожим
.foo
и..foo
работает в одном пакете. Прохладно!Если вы искренне хотите соединить шаблоны загрузки исходного кода с файловой системой, вы можете сделать это. Вам придется выбрать собственную эвристику и использовать какую-то импортную технику, я рекомендую импортное importlib
Пример importlib в Python выглядит примерно так:
упаковка
Официально представлен отличный пример проекта: https://github.com/pypa/sampleproject.
Пакет Python - это набор информации о вашем исходном коде, который может сообщить другим инструментам, как копировать ваш исходный код на другие компьютеры и как интегрировать ваш исходный код в путь этой системы, чтобы он
import foo
работал на других компьютерах (независимо от интерпретатора, операционная система хоста и т. д.)Структура каталогов
Позволяет иметь имя пакета
foo
в некотором каталоге (предпочтительно пустой каталог).Я предпочитаю создавать
setup.py
как братfoo.py
, так как это упрощает написание файла setup.py, однако вы можете написать конфигурацию для изменения / перенаправления всего, что setuptools делает по умолчанию, если хотите; например, размещениеfoo.py
в каталоге "src /" несколько популярно, здесь не рассматривается.,
,
«редактируемый» aka
-e
еще раз перенаправит импортирующий механизм для загрузки исходных файлов в этот каталог, вместо этого копируя текущие точные файлы в библиотеку установочной среды. Это также может вызвать поведенческие различия на компьютере разработчика, обязательно протестируйте свой код! Есть и другие инструменты, кроме pip, однако я бы рекомендовал pip быть вводным :)Мне также нравится делать
foo
«пакет» (директория, содержащая__init__.py
) вместо модуля (один файл «.py»), и «пакеты», и «модули» могут быть загружены в корневое пространство имен, модули допускают вложенные пространства имен, что полезно, если мы хотим иметь импорт «на одну директорию вверх».,
Мне также нравится делать a
foo/__main__.py
, это позволяет python выполнять пакет как модуль, напримерpython3 -m foo
, выполнятьfoo/__main__.py
как__main__
.,
Давайте уточним это с помощью еще нескольких модулей: в основном, вы можете иметь структуру каталогов, например:
setup.py
условно содержит метаданные о исходном коде, такие как:foo
, хотя замена дефисов подчеркиванием является популярнымpython ./setup.py test
Она очень обширна, она может даже компилировать расширения c на лету, если на машине разработчика устанавливается исходный модуль. В качестве примера на каждый день я рекомендую файл setup.py репозитория образцов PYPA
Если вы выпускаете артефакт сборки, например, копию кода, предназначенного для запуска практически идентичных компьютеров, файл require.txt - это популярный способ получения точной информации о зависимостях, где «install_requires» - это хороший способ собрать минимум и максимально совместимые версии. Однако, учитывая, что целевые машины в любом случае почти идентичны, я настоятельно рекомендую создать тарбол с полным префиксом python. Это может быть сложно, слишком подробно, чтобы попасть сюда. Проверьте
pip install
's--target
вариант, или virtualenv aka venv для лидов.вернуться к примеру
Как импортировать файл на один каталог вверх:
Из foo / spam / eggs.py, если мы хотим получить код из foo / baz, мы можем запросить его по абсолютному пространству имен:
Если бы мы хотели зарезервировать возможность в будущем переместить eggs.py в какой-либо другой каталог с другой относительной
baz
реализацией, мы могли бы использовать относительный импорт, например:источник
Python - это модульная система
Python не полагается на файловую систему
Чтобы надежно загрузить код Python, поместите этот код в модуль, и этот модуль должен быть установлен в библиотеке Python.
Установленные модули всегда можно загрузить из пространства имен верхнего уровня с помощью
import <name>
Официально представлен отличный пример проекта: https://github.com/pypa/sampleproject.
По сути, вы можете иметь структуру каталогов следующим образом:
,
Обязательно объявить
setuptools.setup()
по прибытиюsetup.py
,официальный пример: https://github.com/pypa/sampleproject/blob/master/setup.py
В нашем случае мы, вероятно, хотим экспортировать,
bar.py
иfoo/__init__.py
мой краткий пример:setup.py
,
Теперь мы можем установить наш модуль в библиотеку Python; с помощью pip вы можете установить
the_foo_project
вашу библиотеку python в режиме редактирования, чтобы мы могли работать с ней в режиме реального времени,
Теперь из любого контекста Python мы можем загрузить наши общие py_modules и пакеты
foo_script.py
источник
pip install --edit foo
, почти всегда внутри virtualenv. Я почти никогда не пишу модуль, который не предназначен для установки. если я что-то неправильно понимаю, я хотел бы знать.editable
ссылки на egg и установленные модули python не совсем одинаковы во всех отношениях; например, добавление нового пространства имен в редактируемый модуль будет найдено в вашем пути поиска, но если это не экспортируется в ваш файл setup.py, он не будет упакован / установлен! Проверьте ваш вариант использования :)