Импортировать пакет python из локального каталога в интерпретатор

87

Я разрабатываю / тестирую пакет в моем локальном каталоге. Я хочу импортировать его в интерпретатор (v2.5), но sys.path не включает текущий каталог. Прямо сейчас набираю sys.path.insert(0,'.'). Есть ли способ лучше?

Также,

from . import mypackage

не работает с этой ошибкой:

ValueError: Attempted relative import in non-package
проекты имеют
источник
Где вы это прочитали "." был модуль Python?
S.Lott
16
@Lott: Это относительный путь импорта, описанный здесь: docs.python.org/reference/…
projectshave
1
Вы можете посмотреть это исчерпывающее
Кевин Чжу

Ответы:

45

Вы можете использовать относительный импорт только из модуля, который, в свою очередь, был импортирован как часть пакета - ваш скрипт или интерактивный интерпретатор не использовались, поэтому, конечно from . import(что означает «импорт из того же пакета, из которого я был импортирован») не не работает. import mypackageбудет хорошо , как только вы убедитесь , родительский каталог mypackageнаходится в sys.path(как вам удалось получить текущий каталог прочь от sys.pathя не знаю - есть ли у вас что - то странное в site.py, или ...)

На sys.pathсамом деле нет лучшего способа вернуть ваш текущий каталог, чем поместить его туда.

Алекс Мартелли
источник
Python 2.5 для Ubuntu 8.10 не имеет текущего каталога (пустой строки) в sys.path для интерпретатора. Я ничего не менял, так что как-то так и доставили. Я только что установил 3.0, и в sys.path ЕСТЬ '' '' в sys.path.
projectshave
@projectshave, хорошо, у Ubuntu, без сомнения, есть свои причины! Я не заметил этого в 8.04 (то, что мы сейчас используем на работе), но, возможно, я просто не уделял достаточно внимания.
Alex Martelli
1
Я частично ошибаюсь. Python, вызываемый из оболочки, имеет текущий каталог в sys.path. Python, вызванный из Emacs, не имеет текущего каталога. Странный.
projectshave
1
Ну что ж, тогда у Emacs есть свои причины в отличие от Ubuntu (как пользователь vim я действительно не знаю ;-). Вы можете условно вставить '.' в вашем sys.path, если, конечно, нет.
Alex Martelli
@Alex Martelli: Большое вам спасибо! Я искал и искал решение, почему моему надстройке (для Anki) нужен другой оператор импорта при запуске «локально» в качестве сценария. Когда я вместо этого добавил метод local_launch () и импортировал / запустил все это из сценария вне папки пакета, это сработало как шарм!
Джон Кумбс
17

См. Документацию для sys.path:

http://docs.python.org/library/sys.html#sys.path

Цитировать:

Если каталог сценария недоступен (например, если интерпретатор вызывается в интерактивном режиме или если сценарий читается со стандартного ввода), путь [0] является пустой строкой, которая направляет Python на поиск модулей в текущем каталоге в первую очередь.

Таким образом, нет необходимости использовать sys.path, если вы запускаете интерпретатор python из каталога, содержащего ваш модуль.

Кроме того, чтобы импортировать ваш пакет, просто выполните:

import mypackage

Поскольку каталог, содержащий пакет, уже находится в sys.path, он должен работать нормально.

SpoonMeiser
источник
1
Это не удастся, если подобное имя файла существует где-то еще в рабочем окружении.
JAR.JAR.beans 07
@ JAR.JAR.beans текущий рабочий каталог должен быть первым, sys.pathпоэтому файлы в нем должны быть найдены раньше файлов где-либо еще в рабочей среде.
SpoonMeiser 07
3
Хорошая точка зрения. То есть, если мы запустим файл из локального каталога. В случае, если это какая-то другая папка, и в случае, если необходимо изменить sys.path - это означает, sys.path.insert(0, new_path)а не sys.path.append(new_path).
JAR.JAR.beans 07
14

Если вы хотите запустить немодифицированный скрипт python, чтобы он импортировал библиотеки из определенного локального каталога, вы можете установить PYTHONPATHпеременную среды, например, в bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

Если вы просто хотите импортировать его из текущего рабочего каталога, используйте .обозначение:

export PYTHONPATH=.
python myscript.py
Pierz
источник
Экспорт PYTHONPATH включает программирование вне Python (например, в bash). Кроме того, в docs.python.org/3/using/cmdline.html четко указано, что « путь поиска по умолчанию зависит от установки ».
ilias iliadis
13

Будь проще:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Гвидо У. Драхейм
источник
7
Мне нравится это решение, оно самое простое. Единственный оставшийся вопрос: почему правило «только один способ сделать это» было сочтено необязательным при реализации импорта ... Серьезно, существует около 15 способов объявить и организовать пакеты, у всех из которых есть недостатки,
Лео Жермон,
5

Простой способ заставить его работать - запустить ваш скрипт из родительского каталога с помощью -mфлага python , например python -m packagename.scriptname. Очевидно, что в этой ситуации вам понадобится __init__.pyфайл, чтобы превратить ваш каталог в пакет.

bradley.ayers
источник
5

Внутри пакета если есть setup.py , то лучше его установить

pip install -e .
Нагашаян
источник
3

Использование sys.pathдолжно уже включать текущий каталог.

Пытаться:

import .

или:

from . import sth

однако это может быть не очень хорошей практикой, так почему бы просто не использовать:

import mypackage
Суньцян
источник
5
Проблема с <import mypackage> заключается в том, что он загружает пакет из глобального окружения python, он может загружать пакет / файл из локальной папки, но с таким же успехом может загружать какой-то другой случайный mypackge, который находится в рабочем окружении.
JAR.JAR.beans 07
2

Немного поздно на вечеринку, но вот что сработало для меня:

>>> import sys
>>> sys.path.insert(0, '')

По-видимому, если есть пустая строка, Python знает, что он должен искать в текущем каталоге. У меня не было пустой строки sys.path, что вызвало эту ошибку.

человеккомпьютер
источник
0

Раньше я pathlibдобавлял свой каталог модуля в свой системный путь, так как хотел избежать установки модуля как пакета, и ответ @maninthecomputer у меня не работал

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
рдмолония
источник