2013-05-03 20 views
6

Also, ich habe ein paar ähnliche Fragen zu Stack Overflow gesehen, aber nichts scheint mein Problem oder den allgemeinen Fall anzusprechen. Also, hoffentlich behebt diese Frage das und stoppt meine Kopfschmerzen. Ich habe ein Git-Repo der Form:Importieren von Schwesterunterverzeichnissen in Python?

repo/ 
    __init__.py 
    sub1/ 
     __init__.py 
     sub1a/ 
     __init.py 
     mod1.py 
    sub2/ 
     __init__.py 
     mod2.py 

Wie kann ich mod2.py von mod1.py und umgekehrt importieren, und wie funktioniert diese Änderung je nachdem, ob mod1.py oder mod2.py sind Skripte (wenn jeweils wird importiert - nicht importiert)?

Antwort

6

Die einfachste Lösung ist, das Verzeichnis, das repo enthält, in Ihre PYTHONPATH zu setzen und dann nur absolute Pfadimporte zu verwenden, z. import repo.sub2.mod2 und so weiter.

Jede andere Lösung wird einige hackery einzubeziehen, wenn Sie es wollen, Fälle, in denen Sie sowohl die Python-Dateien direkt als Skripte aus beliebigen Verzeichnissen sind aufgerufen wird - höchstwahrscheinlich sys.path Mangeln, um effektiv das Gleiche zu erreichen wie Einstellung PYTHONPATH, aber ohne dass der Benutzer es einstellen muss.

+1

Mir geht es gut mit der Bearbeitung von PYTHONPATH, aber gibt es einen Standard Weg dies zu erzwingen? Ich möchte nicht, dass alle neuen Benutzer des Repos manuell ihren PYTHONPATH aktualisieren müssen. – Eli

+1

Wenn Sie nicht möchten, dass Benutzer 'PYTHONPATH' selbst verwalten müssen, müssen Sie' sys.path' mangling berücksichtigen. (Verwenden Sie zum Beispiel '__file__' plus' os.abspath', um nach dem Ort des Skripts zu suchen, und rufen Sie dann das Verzeichnis mit der richtigen Anzahl von darüber liegenden Ebenen als 'repo'-Elternteil und dann' sys.path.insert auf 'it.) – Amber

2

Wenn Sie Python verwenden 2.6+, haben Sie zwei Möglichkeiten:

  • Relative Importe
  • Hinzufügen repo zu Ihrem PYTHONPATH

Bei relativen Einfuhren wird eine spezielle Punkt-Syntax verwendet:

im Paket unter1:

from .sub2.mod2 import thing 

in Paket sub1a:

from ..sub2.mod2 import otherthing 

Beachten Sie, dass Ebene Import-Anweisungen (import module) nicht mit relativen Importen arbeiten.

wäre eine bessere Lösung absolute Importe mit Ihrer Python-Pfad richtig (zB in bash) eingestellt werden:

export PYTHONPATH=/where/your/project/is:$PYTHONPATH 

Weitere Informationen:

+0

Ich wollte wirklich, dass diese relativen Importe funktionieren. Auf meinem Python 2.7 funktionieren sie jedoch nicht. –

+0

Mit Python 2.7 hatte ich Erfolg mit Anweisungen wie 'from sub2.mod2 import thing'. – coralvanda

0

Ein Skript oder Modul kann Module importieren, die entweder

  1. auf dem Systempfad oder
  2. Teil des gleichen Pakets wie der Import/script-Modul.

Für Module gelten diese Regeln ohne Ausnahme. Für Skripts gelten die Regeln, aber das Problem besteht darin, dass beim Ausführen eines Skripts standardmäßig nicht davon ausgegangen wird, dass es Teil eines Pakets ist.

Dies bedeutet, dass ein Skript standardmäßig nur Module importieren kann, die sich auf dem Systempfad befinden. Standardmäßig enthält der Pfad das aktuelle Verzeichnis. Wenn Sie also ein Skript ausführen, können Module in dasselbe Verzeichnis oder in Pakete importiert werden, die Unterverzeichnisse sind. Aber das ist es. Ein Skript hat in der Verzeichnisstruktur keine Ahnung von "wo es ist". Daher kann es keine Importe ausführen, die bestimmte relative Pfadinformationen über umschließende Verzeichnisse benötigen. Das heißt, Sie können keine Dinge "aus dem übergeordneten Verzeichnis" oder "aus einem gleichgeordneten Verzeichnis" importieren. Dinge, die sich in diesen Verzeichnissen befinden, können nur importiert werden, wenn sie sich auf dem Systempfad befinden.

Wenn Sie ein Skript "wissen" möchten, das in einem Paket ist, können Sie ihm ein __package__ Attribut geben. Siehe this previous question. Sie können dann explizite relative Importe (z. B. from ...sub2 import mod2) normalerweise innerhalb dieses Skripts verwenden.