Імпортуйте пакет python з локального каталогу в інтерпретатор


86

Я розробляю / тестую пакет у своєму локальному каталозі. Я хочу імпортувати його в інтерпретатор (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
Можливо, ви захочете поглянути на цей остаточний посібник chrisyeh96.github.io/2017/08/08/…
Кевін Чжу

Відповіді:


44

Ви можете використовувати відносний імпорт лише з модуля, який, в свою чергу, був імпортований як частина пакета - ваш скрипт чи інтерактивний інтерпретатор не були, тому, звичайно 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 iff, звичайно, немає.
Алекс Мартеллі,

@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, він повинен працювати нормально.


1
Це не вдасться, якщо подібне ім’я файлу існує десь ще в робочому середовищі.
JAR.JAR.beans

@ JAR.JAR.beans поточний робочий каталог повинен бути першим ділом, sys.pathтому файли там повинні знаходитись перед файлами де-небудь ще в робочому середовищі.
SpoonMeiser

3
Гарна думка. Тобто, якщо ми запускаємо файл із локального каталогу. У випадку, якщо це інша папка, а у випадку, якщо потрібна зміна sys.path - це означає, sys.path.insert(0, new_path)а не sys.path.append(new_path).
JAR.JAR.beans

14

Якщо ви хочете запустити немодифікований скрипт python, щоб він імпортував бібліотеки з певного локального каталогу, ви можете встановити PYTHONPATHзмінну середовища - наприклад, у bash:

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

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

export PYTHONPATH=.
python myscript.py

Експорт 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файл, щоб перетворити ваш каталог у пакет.



3

Використовуючи sys.path має включати вже поточний каталог.

Спробуйте:

import .

або:

from . import sth

однак це може бути не найкращою практикою, то чому б просто не використовувати:

import mypackage

5
Проблема з <import mypackage> полягає в тому, що він завантажує пакет з глобального python env, він може завантажувати пакет / файл з локальної папки, але він може так само завантажувати деякі інші випадкові mypackge, що знаходяться в робочому середовищі.
JAR.JAR.beans

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.