Importuj pakiet Pythona z lokalnego katalogu do interpretera

86

Rozwijam / testuję pakiet w moim katalogu lokalnym. Chcę go zaimportować do interpretera (v2.5), ale sys.path nie zawiera bieżącego katalogu. Teraz wpisuję sys.path.insert(0,'.'). Czy jest lepszy sposób?

Również,

from . import mypackage

kończy się niepowodzeniem z tym błędem:

ValueError: Attempted relative import in non-package
projectshave
źródło
Gdzie to przeczytałeś „.” był modułem Pythona?
S.Lott,
16
@Lott: To względna ścieżka importu opisana tutaj: docs.python.org/reference/…
projectshave,
1
Możesz spojrzeć na ten ostateczny przewodnik chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Odpowiedzi:

44

Możesz użyć importu względnego tylko z modułu, który z kolei został zaimportowany jako część pakietu - twój skrypt lub interaktywny interpreter nie był, więc oczywiście from . import(co oznacza "import z tego samego pakietu, z którego zostałem zaimportowany") nie nie działa. import mypackagebędzie dobrze raz upewnić katalogu nadrzędnego mypackagejest sys.path(jak udało Ci się aktualny katalog z dala od sys.pathnie wiem - czy masz coś dziwnego w site.py, albo ...)

sys.pathNie ma lepszego sposobu na przywrócenie tam obecnego katalogu niż umieszczenie go tam.

Alex Martelli
źródło
Python 2.5 dla Ubuntu 8.10 nie ma bieżącego katalogu (pusty ciąg znaków) w sys.path dla interpretera. Niczego nie zmieniłem, więc jakoś został wysłany w ten sposób. Właśnie zainstalowałem 3.0, a sys.path MA '' w sys.path.
projectshave
@projectshave, OK, Ubuntu bez wątpienia ma swoje powody! Nie zauważyłem tego w 8.04 (co obecnie używamy w pracy), ale może po prostu nie zwracałem wystarczającej uwagi.
Alex Martelli,
1
Po części się mylę. Python wywołany z powłoki ma bieżący katalog w sys.path. Python wywołany z Emacsa nie ma bieżącego katalogu. Dziwne.
projectshave
1
No cóż, to Emacs ma swoje powody, a nie Ubuntu (jako użytkownik vima nie znam ;-). Możesz warunkowo wstawić „.” w twoim sys.path tam, oczywiście, nie ma.
Alex Martelli
@Alex Martelli: Dziękuję bardzo! Szukałem i szukałem rozwiązania, dlaczego mój dodatek (dla Anki) wymagał innej instrukcji importu, gdy był uruchamiany „lokalnie” jako skrypt. Kiedy zamiast tego dodałem metodę local_launch () i zaimportowałem / uruchomiłem całość ze skryptu poza folderem pakietu, zadziałało to jak urok!
Jon Coombs
17

Zobacz dokumentację sys.path:

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

Cytować:

Jeśli katalog skryptu nie jest dostępny (np. Jeśli interpreter jest wywoływany interaktywnie lub jeśli skrypt jest czytany ze standardowego wejścia), ścieżka [0] jest pustym ciągiem, który kieruje Pythona do wyszukiwania modułów w bieżącym katalogu w pierwszej kolejności.

Więc nie ma potrzeby małpowania z sys.path, jeśli uruchamiasz interpreter Pythona z katalogu zawierającego twój moduł.

Aby zaimportować pakiet, po prostu wykonaj:

import mypackage

Ponieważ katalog zawierający pakiet jest już w sys.path, powinien działać dobrze.

SpoonMeiser
źródło
1
Nie powiedzie się, jeśli podobna nazwa pliku istnieje w innym miejscu w działającym środowisku.
JAR.JAR.beans
@ JAR.JAR.beans bieżący katalog roboczy powinien być pierwszym, sys.pathwięc pliki w nim zawarte powinny znajdować się przed plikami w innym miejscu w środowisku roboczym.
SpoonMeiser
3
Słuszna uwaga. To znaczy, jeśli uruchomimy plik z katalogu lokalnego. W przypadku, gdy jest to inny folder, aw przypadku, gdy potrzebna jest zmiana na sys.path - oznacza to sys.path.insert(0, new_path)raczej niż sys.path.append(new_path).
JAR.JAR.beans
14

Jeśli chcesz uruchomić niezmodyfikowany skrypt w Pythonie, aby importował biblioteki z określonego katalogu lokalnego, możesz ustawić PYTHONPATHzmienną środowiskową - np. W bash:

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

Jeśli chcesz po prostu zaimportować z bieżącego katalogu roboczego, użyj .notacji:

export PYTHONPATH=.
python myscript.py
Pierz
źródło
Eksportowanie PYTHONPATH obejmuje programowanie poza Pythonem (np. W bash). Ponadto w docs.python.org/3/using/cmdline.html jest jasno określone, że „ domyślna ścieżka wyszukiwania zależy od instalacji ”.
ilias iliadis
13

Nie komplikuj:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Guido U. Draheim
źródło
7
Podoba mi się to rozwiązanie, jest najprostsze. Pozostaje tylko pytanie, dlaczego zasada „jedynego sposobu, aby to zrobić” została uznana za opcjonalną podczas implementacji importu ... Poważnie istnieje około 15 sposobów deklarowania i organizowania paczek, z których wszystkie mają wady
Léo Germond
5

Prostym sposobem, aby to działało, jest uruchomienie skryptu z katalogu nadrzędnego za pomocą -mflagi Pythona , np python -m packagename.scriptname. Oczywiście w tej sytuacji potrzebujesz __init__.pypliku, aby zamienić katalog w pakiet.

bradley.ayers
źródło
5

W pakiecie, jeśli jest setup.py , lepiej go zainstalować

pip install -e .
Nagashayan
źródło
3

Użycie sys.pathpowinno już zawierać bieżący katalog.

Próbować:

import .

lub:

from . import sth

jednak może to nie być dobra praktyka, więc dlaczego nie użyć po prostu:

import mypackage
sunqiang
źródło
5
Problem z <import mypackage> polega na tym, że załaduje pakiet z globalnego środowiska Pythona, może załadować pakiet / plik z folderu lokalnego, ale równie dobrze może załadować inny losowy mypackge, który znajduje się w działającym środowisku.
JAR.JAR.beans
2

Trochę za późno na imprezę, ale tak mi się udało:

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

Najwyraźniej, jeśli istnieje pusty ciąg, Python wie, że powinien on szukać w bieżącym katalogu. Nie miałem pustego ciągu sys.path, co spowodowało ten błąd.

maninthekomputer
źródło
0

Kiedyś pathlib, aby dodać mój katalog modułu do mojej ścieżce systemowej, jak chciałem, aby uniknąć instalowania modułu jako pakiet i @maninthecomputer odpowiedzi nie działa dla mnie

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
rdmolony
źródło