Как импортировать модуль Python с указанием его относительного пути?
Например, если dirFoo
содержит Foo.py
и dirBar
, и dirBar
содержит Bar.py
, как я могу импортировать Bar.py
в Foo.py
?
Вот визуальное представление:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
хочет включить Bar
, но реструктуризация иерархии папок не вариант.
python
relative-path
python-import
Джуд аллред
источник
источник
Ответы:
Предполагая, что обе ваши директории являются реальными пакетами Python (в них есть
__init__.py
файл), здесь есть безопасное решение для включения модулей относительно места расположения скрипта.Я предполагаю, что вы хотите сделать это, потому что вам нужно включить набор модулей в ваш скрипт. Я использую это в производстве в нескольких продуктах и работает во многих специальных сценариях, таких как: сценарии, вызываемые из другого каталога или выполняемые с использованием python, вместо открытия нового интерпретатора.
В качестве бонуса этот подход позволяет вам заставить Python использовать ваш модуль вместо установленных в системе.
Предупреждение! Я действительно не знаю, что происходит, когда текущий модуль находится внутри
egg
файла. Это, вероятно, тоже терпит неудачу.источник
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
Do НЕ добавить вложенный перед тем,abspath
как это вызывает серьезные ошибки.cmd_subfolder
) прямо к моему ответу. Спасибо!realpath
уже генерируются абсолютные пути, поэтому я не нуждаюсьabspath
. Такжеos.path.dirname
может использоваться вместо split, что делает индексирование[0]
устаревшим. Строка будет:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Убедитесь, что у dirBar есть
__init__.py
файл - это превращает каталог в пакет Python.источник
sys.path
то присутствие__init__.py
в этомdirBar
каталоге мало помогает.__init.py__
будет работать только тогда, когда каталог уже находится в sys.path, а в моем случае это не так. Решение "сорина" (принятого) всегда работает.sys.path
вопросе? Возможно, было что-то пропущено, что мы не видели или не знали?Вы также можете добавить подкаталог в путь Python, чтобы он импортировался как обычный скрипт.
источник
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
как он будет загружать этот модуль до того, как модули с тем же именем будут сохранены в другом месте.источник
os.path.join()
вместо объединения символ '/', который сломается в (хромых) окнах.os.path.abspath(os.path.join(__file__,'..','lib'))
?Просто сделайте простые вещи, чтобы импортировать файл .py из другой папки.
Допустим, у вас есть каталог вроде:
Затем просто сохраните пустой файл в папке lib с именем
А потом использовать
Храните
__init__.py
файл в каждой папке иерархии модуля импорта.источник
Если вы структурируете свой проект следующим образом:
Тогда из Foo.py вы сможете сделать:
Или:
Согласно комментарию Тома, для этого требуется, чтобы
src
папка была доступна либо черезsite_packages
ваш путь поиска. Кроме того, как он упоминает,__init__.py
он неявно импортируется при первом импорте модуля в этот пакет / каталог. Обычно__init__.py
это просто пустой файл.источник
from dirFoo import Foo
сказатьFoo.bla()
. Если использоватьimport dirFoo.Foo
один должен использоватьdirFoo.Foo.bla()
- довольно некрасиво, даже без случая верблюда.Самый простой способ - использовать sys.path.append ().
Тем не менее, вы также можете быть заинтересованы в модуле Imp . Предоставляет доступ к внутренним функциям импорта.
Это может быть использовано для динамической загрузки модулей, когда вы не знаете имени модуля.
Я использовал это в прошлом для создания интерфейса типа плагина к приложению, где пользователь мог бы написать сценарий с функциями, специфичными для приложения, и просто поместить их в определенный каталог.
Также эти функции могут быть полезны:
источник
Это соответствующий ПКП:
http://www.python.org/dev/peps/pep-0328/
В частности, предполагается, что dirFoo является каталогом от dirBar ...
В dirFoo \ Foo.py:
источник
Самый простой способ без каких-либо изменений в вашем скрипте - установить переменную окружения PYTHONPATH. Потому что sys.path инициализируется из этих мест:
Просто беги:
Ваш sys.path будет содержать вышеуказанный путь, как показано ниже:
источник
На мой взгляд, лучший выбор - поместить __ init __.py в папку и вызвать файл с
Не рекомендуется использовать sys.path.append (), потому что что-то может пойти не так, если вы используете то же имя файла, что и существующий пакет Python. Я не проверял это, но это будет неоднозначно.
источник
from dirBar.Bar import *
работает, но нетfrom dirBar.Bar import Bar
. ты знаешь почему * работает? Что делать, если у меня было несколько файлов в dirBar /, и я хотел получить только несколько из них (используя метод, подобный тому, который вы опубликовали здесь)?from dirBar import Bar
.from
указывает на источник, а все, что после,import
- это то, что нужно взять из этого источника.from dirBar.Bar import Bar
означает «Из источника, импортируйте сам источник», что не имеет смысла. что*
хотя средства, «дают мне все , от источника»Быстрый и грязный способ для пользователей Linux
Если вы просто возитесь и не заботитесь о проблемах развертывания, вы можете использовать символическую ссылку (при условии, что ваша файловая система поддерживает ее), чтобы сделать модуль или пакет непосредственно видимым в папке запрашивающего модуля.
или
Примечание. «Модуль» - это любой файл с расширением .py, а «пакет» - любая папка, в которой находится файл
__init__.py
(который может быть пустым файлом). С точки зрения использования модули и пакеты идентичны - оба предоставляют свои «определения и утверждения» в соответствии с запросом черезimport
команды.Смотрите: http://docs.python.org/2/tutorial/modules.html
источник
вместо:
на всякий случай может быть установлен еще один dirBar, который запутает читателя foo.py.
источник
Для этого случая, чтобы импортировать Bar.py в Foo.py, сначала я бы превратил эти папки в пакеты Python:
Тогда я бы сделал это так в Foo.py:
Если бы я хотел, чтобы пространство имен выглядело как Бар. что угодно , или
Если бы я хотел пространство имен dirBar.Bar. независимо . Этот второй случай полезен, если у вас есть больше модулей в пакете dirBar.
источник
Добавьте файл __init__.py :
Затем добавьте этот код в начало Foo.py:
источник
dirBar
уже есть пакет Python (существованиеdirBar/__init__.py
), нет необходимости добавлятьdirBar
кsys.path
, нет? Утверждениеimport Bar
отFoo.py
должно хватить.Относительный пример sys.path:
На основании этого ответа.
источник
Ну, как вы упоминаете, обычно вы хотите иметь доступ к папке с вашими модулями относительно места запуска вашего основного скрипта, поэтому вы просто импортируете их.
Решение:
У меня есть скрипт
D:/Books/MyBooks.py
и некоторые модули (например, oldies.py). Мне нужно импортировать из подкаталогаD:/Books/includes
:Поместите
print('done')
в системуoldies.py
, так что вы убедитесь , что все идет ОК. Этот способ всегда работает, потому что по определению Python,sys.path
инициализированному при запуске программы, первый элемент этого списка,path[0]
является каталог, содержащий скрипт, который использовался для вызова интерпретатора Python.Если каталог скриптов недоступен (например, если интерпретатор вызывается в интерактивном режиме или если скрипт читается из стандартного ввода),
path[0]
это пустая строка, которая направляет Python для поиска модулей в текущем каталоге в первую очередь. Обратите внимание, что каталог скриптов вставляется перед записями, вставленными в результатеPYTHONPATH
.источник
site.addsitedir(sys.path[0]+'/includes')
) в моей первой простой программе на Python break_time.py: https://github.com/ltfschoen/PythonTest . Я использую систему: MacOS v10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Просто вы можете использовать:
from Desktop.filename import something
Пример:
код:
Но убедитесь, что вы делаете пустой файл с именем "
__init__.py
" в этом каталогеисточник
import something
потом сказал, что сделать его проще, в*
принципе, это не хорошо для оперативной памяти, а также, если 2 функции имеют одинаковое имя, это будетДругим решением было бы установить пакет py-require и затем использовать следующее в
Foo.py
источник
require()
функция, вы можете взглянуть на мой проект Node.py: github.com/nodepy/nodepyВот способ импортировать файл с уровня выше, используя относительный путь.
По сути, просто переместите рабочий каталог на уровень (или любое другое относительное местоположение), добавьте его к своему пути, а затем переместите рабочий каталог туда, где он начался.
источник
У меня нет опыта работы с питоном, поэтому, если в моих словах что-то не так, просто скажите мне. Если ваша файловая иерархия устроена так:
module_1.py
определяет функцию с именемfunc_1()
, module_2.py :и вы запускаете
python module_2.py
в CMD, он будет запускать то, чтоfunc_1()
определяет. Обычно мы импортируем одни и те же файлы иерархии. Но когда вы пишетеfrom .module_1 import func_1
вmodule_2.py
питона переводчик скажетNo module named '__main__.module_1'; '__main__' is not a package
. Таким образом, чтобы исправить это, мы просто сохраняем изменения, которые мы просто вносим, и перемещаем оба модуля в пакет, и создаем третий модуль в качестве вызывающего для запускаmodule_2.py
.main.py :
Но причина, по которой мы добавляем
.
ранее, состоитmodule_1
вmodule_2.py
том, что если мы не сделаем этого и не запустимmain.py
, интерпретатор Python скажетNo module named 'module_1'
, что это немного сложно,module_1.py
прямо рядомmodule_2.py
. Теперь я позволяюfunc_1()
вmodule_1.py
сделай что - нибудь:что
__name__
записывает кто звонит func_1. Теперь мы держим.
доmodule_1
, запуститьmain.py
, он будет печататьpackage_1.module_1
, а неmodule_1
. Это означает, что тот, кто вызывает,func_1()
находится в той же иерархииmain.py
, что и.
подразумевает, чтоmodule_1
находится в той же иерархии, что и онmodule_2.py
сам. Так что, если нет точки,main.py
она распознаетmodule_1
в той же иерархии, что и сама, она может распознатьpackage_1
, но не то, что «под ней».Теперь давайте сделаем это немного сложнее. У вас есть
config.ini
и модуль определяет функцию для чтения в той же иерархии, что и «main.py».И по какой-то неизбежной причине вы должны вызывать его с помощью функции
module_2.py
импорта из верхней иерархии. module_2.py :Две точки означают импорт из верхней иерархии (три точки имеют доступ выше верхней и т. Д.). Теперь мы запускаем
main.py
интерпретатор скажет:ValueError:attempted relative import beyond top-level package
. «Пакет верхнего уровня» здесьmain.py
. Просто потому , что ониconfig.py
рядомmain.py
, они находятся в той же иерархии,config.py
не «под»main.py
или не «ведомы»main.py
, так что это за их пределамиmain.py
. Чтобы это исправить, самый простой способ:Я думаю, что это совпадает с принципом организации файлов проекта иерархии, вы должны расположить модули с разными функциями в разных папках, и просто оставить топ-вызывающего абонента снаружи, и вы можете импортировать, как вы хотите.
источник
Это также работает, и намного проще, чем что-либо с
sys
модулем:источник
Называйте меня чрезмерно осторожным, но мне нравится делать мой более переносимым, потому что небезопасно предполагать, что файлы всегда будут находиться в одном и том же месте на каждом компьютере. Лично у меня есть код, сначала найдите путь к файлу. Я использую Linux, так что мой будет выглядеть так:
Это, конечно, если вы не планируете собрать их вместе. Но если это так, вам все равно не нужны два отдельных файла.
источник