Я использую Python 2.5.
Это мое дерево папок:
ptdraft/
nib.py
simulations/
life/
life.py
(У меня тоже есть __init__.py
в каждой папке, здесь опущено для удобства чтения)
Как импортировать nib
модуль изнутри life
модуля? Я надеюсь, что можно обойтись без возиться с sys.path.
Примечание. Основной модуль, который запускается, находится в ptdraft
папке.
__init__.py
. С.Лотт: Я не знаю, как проверить ...sys.path
илиPYTHONPATH
ответы и проверить отличный ответ np8 . Да, это долго читать. Да, это похоже на большую работу. Но это единственный ответ, который действительно решает проблему правильно и чисто.Ответы:
Кажется, что проблема не связана с тем, что модуль находится в родительском каталоге или чем-то в этом роде.
Вам нужно добавить каталог, который содержит
ptdraft
PYTHONPATHВы сказали, что
import nib
работали с вами, это, вероятно, означает, что вы добавилиptdraft
себя (не его родителя) в PYTHONPATH.источник
import sys
и затемsys.path.append("..\<parent_folder>")
Вы можете использовать относительный импорт (python> = 2.5):
(Что нового в Python 2.5) PEP 328: Абсолютный и относительный импорт
РЕДАКТИРОВАТЬ : добавил еще одну точку "." пройти две посылки
источник
ValueError: Attempted relative import in non-package
__init__.py
файл.__init__.py
- это не единственное, что вам нужно сделать: stackoverflow.com/questions/11536764/…Относительный импорт (как в
from .. import mymodule
) работает только в пакете. Чтобы импортировать «mymodule», который находится в родительском каталоге вашего текущего модуля:редактировать :
__file__
атрибут не всегда дается. Вместо использованияos.path.abspath(__file__)
я теперь предложил использовать модуль inspect для получения имени файла (и пути) текущего файла.источник
sys.path.insert(1, os.path.join(sys.path[0], '..'))
parentdir
, но в одном из путей, уже указанных вsys.path
, есть другой модуль с именем «mymodule». Вставка вparentdir
качестве первого элементаsys.path
списка гарантирует, чтоparentdir
вместо него будет импортирован модуль из .sys.path.insert(1, os.path.realpath(os.path.pardir))
тоже работаетЯ отправил аналогичный ответ также на вопрос об импорте из родственных пакетов. Вы можете увидеть это здесь .
Решение без
sys.path
взломовРезюме
packaged_stuff
)setup.py
сценарий создания, где вы используете setuptools.setup () .pip install -e <myproject_folder>
from packaged_stuff.modulename import function_name
Настроить
Я предполагаю ту же структуру папок, что и в вопросе
Я называю
.
корневую папку, и в моем случае она находится вC:\tmp\test_imports
.меры
1) Добавить
setup.py
в корневую папкуСодержание
setup.py
можно простоВ принципе "любой"
setup.py
будет работать. Это просто минимальный рабочий пример.2) Используйте виртуальную среду
Если вы знакомы с виртуальными средами, активируйте одну и перейдите к следующему шагу. Использование виртуальных сред не является абсолютно обязательным, но они действительно помогут вам в долгосрочной перспективе (когда у вас более 1 проекта ..). Самые основные шаги (запустить в корневой папке)
python -m venv venv
. /venv/bin/activate
(Linux) или./venv/Scripts/activate
(Win)Чтобы узнать больше об этом, просто Google "учебник по Python virtualenv" или подобное. Вам, вероятно, никогда не понадобятся какие-либо другие команды, кроме создания, активации и деактивации.
После того, как вы создали и активировали виртуальную среду, ваша консоль должна дать имя виртуальной среды в скобках.
3) pip установите ваш проект в редактируемое состояние
Установите пакет верхнего уровня,
myproject
используяpip
. Хитрость заключается в использовании-e
флага при установке. Таким образом, он устанавливается в редактируемом состоянии, и все изменения, внесенные в файлы .py, будут автоматически включены в установленный пакет.В корневом каталоге запустите
pip install -e .
(обратите внимание на точку, это означает «текущий каталог»)Вы также можете увидеть, что он установлен с помощью
pip freeze
4) Импорт путем добавления
mainfolder
к каждому импортуВ этом примере
mainfolder
будетptdraft
. Преимущество этого заключается в том, что вы не столкнетесь с конфликтами имен с другими именами модулей (из стандартной библиотеки Python или сторонних модулей).Пример использования
nib.py
life.py
Запуск life.py
источник
sys.path
включены и где код обычно устанавливается конечными пользователями. Это лучше, чемsys.path
хаки (и вы можете включить использование PYTHONPATH в эту категорию хаков путей), потому что это означает, что код в разработке должен вести себя так же, как и для других пользователей. Напротив, при использовании модификаций пути операторы импорта будут разрешаться другим способом.Вы можете использовать путь, зависящий от ОС, в «пути поиска модуля», который указан в sys.path . Таким образом, вы можете легко добавить родительский каталог следующим образом
Если вы хотите добавить родительский каталог,
Это работает как в Python 2 и 3.
источник
Если добавление папки вашего модуля в PYTHONPATH не сработало, вы можете изменить список sys.path в вашей программе, где интерпретатор Python ищет модули для импорта, в документации по Python сказано:
Зная это, вы можете сделать следующее в своей программе:
источник
/path/to/ptdraft
ее необходимо будет отредактировать. Существуют решения, которые обрабатывают текущий каталог файла и таким же образом импортируют его из родительской папки.Не очень много знаю о Python 2.
В Python 3 родительская папка может быть добавлена следующим образом:
... и тогда можно импортировать модули из него
источник
'..'
ведет к каталогу с данным модулем.Вот простой ответ, чтобы вы могли увидеть, как он работает, маленький и кроссплатформенный.
Он использует только встроенные модули (
os
,sys
иinspect
) , поэтому должны работатьна любой операционной системе (ОС) , так как Python предназначен для этого.
Более короткий код для ответа - меньше строк и переменных
Для меньшего количества строк, чем это, замените вторую строку
import os.path as path, sys, inspect
,добавьте
inspect.
в началеgetsourcefile
(строка 3) и удалите первую строку.- однако это импортирует весь модуль, поэтому может потребоваться больше времени, памяти и ресурсов.
Код для моего ответа ( более длинная версия )
Он использует пример из ответа переполнения стека. Как получить путь к текущему
исполняемому файлу в Python? найти источник (имя файла) работающего кода с помощью встроенного инструмента.
Мой код добавляет путь к файлу
sys.path
, в список путей питона, поскольку это позволяет Python для импорта модулей из этой папки.
После импорта модуля в коде рекомендуется запустить
sys.path.pop(0)
новую строку,если в этой добавленной папке есть модуль с тем же именем, что и другой модуль, который будет импортирован
позже в программе. Вам необходимо удалить элемент списка, добавленный до импорта, а не другие пути.
Если ваша программа не импортирует другие модули, безопасно не удалять путь к файлу, потому что
после завершения программы (или перезапуска оболочки Python) любые изменения, внесенные в
sys.path
исчезают.Примечания о переменной имени файла
Мой ответ не использует
__file__
переменную для получения пути к файлу / имени файла исполняемогокода, потому что пользователи здесь часто называют его ненадежным . Вы не должны использовать его
для импорта модулей из родительской папки в программах, используемых другими людьми.
Некоторые примеры, где это не работает (цитата из этого вопроса переполнения стека):
• его нельзя найти на некоторых платформах • иногда это не полный путь к файлу
источник
sys.path.pop(0)
сразу после импорта нужного модуля. Тем не менее, последующий импорт все еще шел в это место. Например, у меня естьapp/config
,app/tools
иapp/submodule/config
. Отsubmodule
, я вставляюapp/
для импортаtools
, затем удаляюapp/
и пытаюсь импортироватьconfig
, но получаюapp/config
вместоapp/submodule/config
.tools
импортов также импортируетсяconfig
из родительского каталога. Поэтому, когда я позже попытался сделатьsys.path.pop(0); import config
внутриsubmodule
, ожидая получитьapp/submodule/config
, я на самом деле получалapp/config
. Очевидно, Python возвращает кэшированную версию модуля с тем же именем, вместо того, чтобы фактически проверятьsys.path
наличие модуля, соответствующего этому имени.sys.path
в этом случае корректность была изменена, Python просто не проверял это из-за того, что модуль с тем же именем уже был загружен.sys.modules
... sys.modules доступны для записи. Удаление ключа сделает недействительной запись в кеше для названного модуля, в результате чего Python начнет новый поиск при следующем импорте. ... Остерегайтесь, хотя, как если бы вы сохранили ссылку на объект модуля, сделали недействительным его кеш, а затем повторно импортировали, эти два объекта будут разными. Напротив,importlib.reload()
будет повторно использовать и повторно инициализировать содержимое модуля ...os.path.realpath(getsourcefile(lambda:0) + "/../..")
. Получит текущий исходный файл с двумя родительскими символами каталога. Я не использовал,os.path.sep
посколькуgetsourcefile
был возвращает строку, используя/
даже в Windows.realpath
позаботится о выделении двух записей каталога из полного пути (в данном случае, имени файла, а затем текущего каталога), который дает родительский каталог.Вот более общее решение, которое включает родительский каталог в sys.path (работает для меня):
источник
import os, sys\n sys.path.insert(0,os.path.pardir)
то же самое, но сортировщик :) (без комментариев в комментариях)os.path.pardir
вы не получите реальный путь родителя, просто относительный путь от того места, куда вы звонитеsys.path.insert()
__file__
переменная, которая может быть ненадежной (не всегда полный путь к файлу, не работает в каждой операционной системе и т. Д.), Как часто упоминают пользователи StackOverflow. Изменение ответа, чтобы не включать его, вызовет меньше проблем и будет более совместимым. Для получения дополнительной информации см. Stackoverflow.com/a/33532002/3787376 .Я обнаружил, что следующий способ работает для импорта пакета из родительского каталога скрипта. В этом примере я хотел бы импортировать функции
env.py
изapp.db
пакета.источник
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path
вообще - плохая идея. Вам нужен какой-то способ ( например ,PYTHONPATH
), чтобы ваша библиотека была доступна для другого кода (иначе это на самом деле не библиотека); просто используйте это все время!Вышеупомянутые решения тоже подойдут. Другое решение этой проблемы
Если вы хотите импортировать что-либо из каталога верхнего уровня. Затем,
Также, если вы хотите импортировать какой-либо модуль из родительского каталога. Затем,
Также, если вы хотите импортировать какой-либо модуль из родительского каталога. Затем,
Таким образом, вы можете импортировать любой конкретный метод, если хотите.
источник
sys.path.append
описано выше, и я не могу импортировать свою библиотеку таким образом. Это то, что я впервые попытался сделать, прежде чем начать Google :) Хорошо, это былоValueError: attempted relative import beyond top-level package
Для меня самый короткий и мой любимый oneliner для доступа к родительскому каталогу:
или:
os.getcwd () возвращает имя текущего рабочего каталога, os.path.dirname (directory_name) возвращает имя каталога для переданного.
На самом деле, по моему мнению, архитектура проекта Python должна быть выполнена так, чтобы ни один модуль из дочернего каталога не использовал ни один модуль из родительского каталога. Если что-то подобное происходит, стоит задуматься о дереве проекта.
Другой способ - добавить родительский каталог в системную переменную среды PYTHONPATH.
источник
В ноутбуке Jupyter
Пока вы работаете в ноутбуке Jupyter, это краткое решение может быть полезным:
Работает даже без
__init__.py
файла.Я протестировал его с Anaconda3 на Linux и Windows 7.
источник
%cd -
после импорта, поэтому текущий каталог ноутбука остается неизменным.import sys sys.path.append('../')
источник
Когда
__init__.py
библиотека не находится в пакетной среде с файлами, библиотека pathlib (включенная в> = Python 3.4) делает очень кратким и интуитивно понятным добавление пути родительского каталога в PYTHONPATH:источник
тот же стиль, что и в прошлом ответе - но в меньшем количестве строк: P
файл возвращает местоположение, в котором вы работаете
источник
Работа с библиотеками. Создайте библиотеку с именем nib, установите ее с помощью setup.py, пусть она будет находиться в пакетах сайтов, и ваши проблемы будут решены. Вам не нужно собирать все, что вы делаете в одной упаковке. Разбейте его на куски.
источник
site-packages
каждый раз, когда они запускают его на другом компьютере.В системе Linux вы можете создать программную ссылку из папки «life» на файл nib.py. Затем вы можете просто импортировать его как:
источник