Ist dies der richtige Weg, um Python-Skripte in beliebigen Ordnern zu importieren?

8

Dieses Snippet stammt von einer früheren Antwort hier auf SO. Es ist ungefähr ein Jahr alt (und die Antwort wurde nicht akzeptiert). Ich bin neu in Python und ich finde den Systempfad einen echten Schmerz. Ich habe ein paar Funktionen in Skripten in verschiedenen Verzeichnissen geschrieben, und ich würde gerne in der Lage sein, sie in neue Projekte zu importieren, ohne durch Ringe springen zu müssen.

Dies ist das Snippet:

%Vor%

Es ist von hier: Wie importieren Sie relative Importe in Python?

Ich hätte gerne ein Feedback, ob ich es benutzen kann oder nicht - und ob es unerwünschte Nebenwirkungen gibt, die einem Neuling vielleicht nicht auffallen.

Ich beabsichtige, es so zu verwenden:

%Vor%

usw.

Ist es "sicher", die Funktion so zu nutzen, wie ich es beabsichtige?

    
morpheous 29.06.2010, 03:50
quelle

4 Antworten

8

Der "offizielle" und völlig sichere Ansatz ist das imp -Modul von die Standard-Python-Bibliothek.

Verwenden Sie imp.find_module , um das Modul auf Ihrer genau angegebenen Seite zu finden Liste der akzeptablen Verzeichnisse - es gibt ein 3-Tupel (file, pathname, description) zurück - wenn nicht erfolgreich, ist file tatsächlich None (aber es kann auch ImportError erhöhen, also solltest du ein try / except dafür verwenden das ebenso wie if file is None: ) überprüfen.

Wenn die Suche erfolgreich ist, rufen Sie imp.load_module (in einer try / finally , um sicherzustellen, dass Sie die Datei schließen!) mit den obigen drei Argumenten nach der ersten, die die gleiche name sein müssen, die Sie an find_module übergeben haben - es gibt das Modul-Objekt zurück (puh; - ).

    
Alex Martelli 29.06.2010, 04:44
quelle
0

Es fühlt sich an wie ein bisschen wie ein Hack, aber im Moment kann ich nicht an unbeabsichtigte Nebenwirkungen denken, die wahrscheinlich auftreten werden, zumindest nicht so lange, wie Sie es nur für Ihre eigenen Skripte verwenden . Im Grunde wird das übergeordnete Verzeichnis der angegebenen Datei (in Ihrem Beispiel /home/pydev/path1/ ) vorübergehend zur Liste der Pfade hinzugefügt, die Python bei der Suche nach einem zu importierenden Modul überprüft.

Das einzige Risiko, das mir gerade einfällt, würde in einer Multithread-Umgebung auftreten, in der zwei oder mehr Threads (oder Prozesse) diese Funktion gleichzeitig ausführen. Wenn Thread A Modul A aus Pfad dirA/A.py importieren möchte und Thread B Modul B aus Pfad dirB/B.py importieren möchte, werden Sie für eine kurze Zeit mit dirA und dirB in sys.path zusammengeführt . Und wenn es eine Datei namens B.py in dirA gibt, ist es möglich, dass Thread B ( dirA/B.py ) statt der gesuchten Datei ( dirB/B.py ) findet und somit das falsche Modul importiert. Aus diesem Grund würde ich es nicht in Produktionscode oder Code verwenden, den Sie an andere Leute verteilen werden (zumindest nicht, ohne sie zu warnen, dass dieser Hack hier ist!). In einer solchen Situation könnten Sie eine komplexere Funktion schreiben, mit der Sie die zu importierende Datei angeben können, ohne die Standardpfade zu stören. (Das ist zum Beispiel mod_python)

    
David Z 29.06.2010 04:12
quelle
0

Ich wäre besorgt, dass Ihr Skriptname mit einem Modul übereinstimmen könnte, das früher im Pfad angezeigt wird. Um diese Angst zu zerstreuen, würde ich den Pfad vollständig durch eine neue Liste ersetzen, die nur das Verzeichnis enthält, das das Modul enthält, und es nach dem Import zurückstellen. Außerdem sollten Sie in eine Art Sperre einschließen , damit mehrere Threads, die versuchen, dasselbe zu tun, sich nicht gegenseitig stören.

    
Gabe 29.06.2010 04:33
quelle
0

Bitte beachten Sie, wie erwähnt, die Fadensicherheit. Ich bevorzuge etwas, das näher an einer Lösung ist, die in einem ähnlichen Beitrag gepostet wird. Die Hauptunterschiede unten: die Verwendung von Einfügen, um die Priorität des Imports anzugeben, die korrekte Wiederherstellung von sys.path mit try ... und schließlich das Festlegen des globalen Namespace.

%Vor%     
Andrew B. 29.06.2010 04:46
quelle

Tags und Links