Importieren Sie das Python-Paket aus dem lokalen Verzeichnis in den Interpreter

83

Ich entwickle / teste ein Paket in meinem lokalen Verzeichnis. Ich möchte es in den Interpreter (v2.5) importieren, aber sys.path enthält nicht das aktuelle Verzeichnis. Im Moment tippe ich ein sys.path.insert(0,'.'). Gibt es einen besseren Weg?

Ebenfalls,

from . import mypackage

schlägt mit diesem Fehler fehl:

ValueError: Attempted relative import in non-package
projekte haben
quelle
Wo hast du das gelesen "." war ein Python-Modul?
S.Lott
16
@Lott: Es ist ein relativer Importpfad, der
Projectshave
Vielleicht möchten Sie sich diesen endgültigen Leitfaden ansehen chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Antworten:

41

Sie können relative Importe nur aus einem Modul verwenden, das wiederum als Teil eines Pakets importiert wurde - Ihr Skript oder interaktiver Interpreter war dies natürlich nicht from . import(was bedeutet, dass "aus demselben Paket importiert wurde, aus dem ich importiert wurde") funktioniert nicht import mypackagein Ordnung sein wird , wenn Sie das übergeordnete Verzeichnis gewährleisten von mypackagein ist sys.path(wie Sie Ihr aktuelles Verzeichnis erhalten verwalten weg von , sys.pathweiß ich nicht - tun Sie etwas seltsam in site.py, oder ...)

sys.pathEs gibt keinen besseren Weg, um Ihr aktuelles Verzeichnis wieder dort abzulegen, als es dort abzulegen.

Alex Martelli
quelle
Python 2.5 für Ubuntu 8.10 verfügt nicht über das aktuelle Verzeichnis (leere Zeichenfolge) in sys.path für den Interpreter. Ich habe nichts geändert, also wurde es irgendwie so verschickt. Ich habe gerade 3.0 installiert und sys.path hat '' in sys.path.
Projekte haben
@projectshave, OK, Ubuntu hat zweifellos ihre Gründe! Ich habe das in 8.04 (was wir derzeit bei der Arbeit verwenden) nicht bemerkt, aber vielleicht habe ich einfach nicht genug Aufmerksamkeit geschenkt.
Alex Martelli
1
Ich liege teilweise falsch. Python, das von einer Shell aufgerufen wird, hat das aktuelle Verzeichnis in sys.path. Von Emacs aufgerufene Python verfügt nicht über das aktuelle Verzeichnis. Seltsam.
Projekte haben
1
Na ja, dann hat Emacs seine Gründe im Gegensatz zu Ubuntu (als Vim-User weiß ich es nicht wirklich ;-). Sie können '.' Bedingt einfügen. in deinem sys.path wenn nicht da natürlich.
Alex Martelli
@ Alex Martelli: Vielen Dank! Ich habe nach einer Lösung gesucht und gesucht, warum mein Add-On (für Anki) eine andere Importanweisung benötigte, wenn es "lokal" als Skript ausgeführt wurde. Als ich stattdessen eine local_launch () -Methode hinzufügte und das Ganze aus einem Skript außerhalb des Paketordners importierte / startete , funktionierte es wie ein Zauber!
Jon Coombs
15

Siehe die Dokumentation zu sys.path:

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

Zitieren:

Wenn das Skriptverzeichnis nicht verfügbar ist (z. B. wenn der Interpreter interaktiv aufgerufen wird oder wenn das Skript von der Standardeingabe gelesen wird), ist Pfad [0] die leere Zeichenfolge, die Python anweist, zuerst Module im aktuellen Verzeichnis zu suchen.

Es ist also nicht erforderlich, mit sys.path einen Affen zu erstellen, wenn Sie den Python-Interpreter über das Verzeichnis starten, in dem sich Ihr Modul befindet.

Um Ihr Paket zu importieren, gehen Sie einfach wie folgt vor:

import mypackage

Da sich das Verzeichnis mit dem Paket bereits in sys.path befindet, sollte es einwandfrei funktionieren.

SpoonMeiser
quelle
1
Es schlägt fehl, wenn ein ähnlicher Dateiname an einer anderen Stelle in der Arbeitsumgebung vorhanden ist.
JAR.JAR.beans
@ JAR.JAR.beans Das aktuelle Arbeitsverzeichnis sollte das erste sein, sys.pathsodass Dateien vor Dateien an anderer Stelle in der Arbeitsumgebung gefunden werden sollten.
SpoonMeiser
3
Guter Punkt. Das heißt, wenn wir die Datei aus dem lokalen Verzeichnis ausführen. In dem Fall handelt es sich um einen anderen Ordner, und in dem Fall ist eine Änderung an sys.path erforderlich - dies bedeutet sys.path.insert(0, new_path)eher als sys.path.append(new_path).
JAR.JAR.beans
12

Halte es einfach:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Guido U. Draheim
quelle
7
Ich mag diese Lösung, sie ist die einfachste. Die einzig verbleibende Frage ist, warum die Regel "Nur eine Möglichkeit, dies zu tun" bei der Implementierung von Importen als optional angesehen wurde. Im Ernst, es gibt ungefähr 15 Möglichkeiten, die Pakete zu deklarieren und zu organisieren, die alle Nachteile haben
Léo Germond,
11

Wenn Sie ein unverändertes Python-Skript ausführen möchten, um Bibliotheken aus einem bestimmten lokalen Verzeichnis zu importieren, können Sie die PYTHONPATHUmgebungsvariable festlegen - z. B. in bash:

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

Wenn Sie nur möchten, dass es aus dem aktuellen Arbeitsverzeichnis importiert wird, verwenden Sie die .Notation:

export PYTHONPATH=.
python myscript.py
Pierz
quelle
Das Exportieren von PYTHONPATH umfasst das Programmieren außerhalb von Python (z. B. in Bash). Darüber hinaus wird in docs.python.org/3/using/cmdline.html klar angegeben, dass "der Standardsuchpfad installationsabhängig ist ".
Ilias Iliadis
5

Eine einfache Möglichkeit, dies zum Laufen zu bringen, besteht darin, Ihr Skript mit dem Python- -mFlag aus dem übergeordneten Verzeichnis auszuführen , z python -m packagename.scriptname. In dieser Situation benötigen Sie natürlich eine __init__.pyDatei, um Ihr Verzeichnis in ein Paket umzuwandeln.

bradley.ayers
quelle
5

Wenn sich in einem Paket setup.py befindet , ist es besser, es zu installieren

pip install -e .
Nagashayan
quelle
3

Die Verwendung sys.pathsollte bereits das aktuelle Verzeichnis enthalten.

Versuchen:

import .

oder:

from . import sth

Es kann jedoch sein, dass dies keine gute Vorgehensweise ist. Warum also nicht einfach Folgendes verwenden:

import mypackage
Sunqiang
quelle
5
Das Problem mit <mypackage importieren> besteht darin, dass das Paket aus der globalen Python-Umgebung geladen wird. Möglicherweise wird das Paket / die Datei aus dem lokalen Ordner geladen, aber es kann genauso gut ein anderes zufälliges Mypackge geladen werden, das sich in der Arbeitsumgebung befindet.
JAR.JAR.beans
1

Ein bisschen spät zur Party, aber das hat bei mir funktioniert:

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

Wenn eine leere Zeichenfolge vorhanden ist, weiß Python anscheinend, dass sie im aktuellen Verzeichnis angezeigt werden sollte. Ich hatte keine leere Zeichenfolge sys.path, was diesen Fehler verursachte.

maninthecomputer
quelle
0

Ich habe pathlibmein Modulverzeichnis zu meinem Systempfad hinzugefügt, da ich vermeiden wollte, das Modul als Paket zu installieren, und die Antwort von @maninthecomputer bei mir nicht funktioniert hat

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
rdmolony
quelle