Soll ich "import os.path" oder "import os" verwenden?

139

Laut der offiziellen Dokumentation , os.pathist ein Modul. Was ist also die bevorzugte Art des Imports?

# Should I always import it explicitly?
import os.path

Oder...

# Is importing os enough?
import os

Bitte antworten Sie NICHT "Importieren osfunktioniert für mich". Ich weiß, es funktioniert momentan auch für mich (ab Python 2.6). Was ich wissen möchte, ist eine offizielle Empfehlung zu diesem Thema. Wenn Sie diese Frage beantworten, veröffentlichen Sie bitte Ihre Referenzen .

Denilson Sá Maia
quelle

Antworten:

157

os.pathfunktioniert auf lustige Weise. Es sieht so aus, als ossollte es ein Paket mit einem Submodul sein path, aber in Wirklichkeit osist es ein normales Modul, mit dem man magisch sys.modulesinjizieren kann os.path. Folgendes passiert:

  • Beim Start von Python werden eine Reihe von Modulen geladen sys.modules. Sie sind nicht an Namen in Ihrem Skript gebunden, aber Sie können auf die bereits erstellten Module zugreifen, wenn Sie sie auf irgendeine Weise importieren.

    • sys.modulesist ein Diktat, in dem Module zwischengespeichert werden. Wenn Sie ein Modul importieren und es bereits irgendwo importiert wurde, wird die Instanz in gespeichert sys.modules.
  • osgehört zu den Modulen, die beim Start von Python geladen werden. Es weist sein pathAttribut einem os-spezifischen Pfadmodul zu.

  • Es wird injiziert, sys.modules['os.path'] = pathso dass Sie " import os.path" tun können, als wäre es ein Submodul.

Ich neige dazu, mich os.pathals ein Modul vorzustellen, das ich verwenden möchte, anstatt als etwas im osModul . Obwohl es nicht wirklich ein Submodul eines Pakets namens ist os, importiere ich es so, wie es eines ist, und das tue ich immerimport os.path . Dies steht im Einklang mit der os.pathDokumentation.


Übrigens führt diese Art von Struktur meiner Meinung nach zu einer frühen Verwirrung vieler Python-Programmierer über Module und Pakete sowie über die Code-Organisation. Das hat wirklich zwei Gründe

  1. Wenn Sie sich osein Paket vorstellen und wissen, dass Sie import osauf das Submodul zugreifen können os.path, werden Sie möglicherweise später überrascht, wenn Sie dies nicht tun import twistedund automatisch zugreifen können, twisted.spreadohne es zu importieren.

  2. Es ist verwirrend, dass dies os.nameeine normale Sache ist, eine Zeichenfolge und os.pathein Modul. Ich strukturiere meine Pakete immer mit leeren __init__.pyDateien, so dass ich auf der gleichen Ebene immer eine Art von Dingen habe: ein Modul / Paket oder anderes Zeug. Mehrere große Python-Projekte verfolgen diesen Ansatz, wodurch tendenziell strukturierterer Code erstellt wird.

Mike Graham
quelle
Hervorragende, sehr informative Antwort! Herzliche Glückwünsche! Obwohl es die Frage nicht direkt beantwortet, enthält es viele nützliche Details. Aber könnten Sie bitte näher auf "Dies steht im Einklang mit der Dokumentation von os.path" eingehen? Wie Chris Hulan sagte, importiert das Beispiel os.walk () nur os anstelle von os.path.
Denilson Sá Maia
3
@Denilson, es enthält eine direkte Antwort: Ich mache es immer import os.pathselbst und denke, das ist ein schöner Weg. Mit "Dies steht im Einklang mit der Dokumentation von os.path " habe ich gemeint, dass es in der Dokumentation unter docs.python.org/library/os.path.html eine eigene Seite erhält .
Mike Graham
1
Wow, os.pyspritzt tatsächlich hinein sys.modules['os.path']. Deshalb from os.path import somethingfunktioniert das eigentlich. Ich war neugierig, wann dies eingeführt wurde und überprüfte die Quelle. Unterhaltsame Tatsache: Dies ist aus dem Jahr 1999, erstmals in Python 1.5.2 enthalten. Das ursprüngliche Commit ist hier .
Bluehorn
29

Gemäß PEP-20 von Tim Peters sind "Explizit besser als implizit" und "Lesbarkeit zählt". Wenn alles, was Sie vom osModul benötigen, unter ist os.path, import os.pathwäre es expliziter und lassen Sie andere wissen, was Sie wirklich interessiert.

Ebenso sagt PEP-20 auch "Einfach ist besser als komplex". Wenn Sie also auch Dinge benötigen, die sich unter dem allgemeineren osDach befinden, import oswäre dies vorzuziehen.

Nick T.
quelle
2
Ich verstehe nicht, wie import oses wirklich darum geht, auf irgendeine sinnvolle Weise "einfach" zu sein. Einfach! = Kurz.
Mike Graham
14
Ich habe mehr versucht darauf hinzuweisen import os und ein import os.pathist dumm, wenn Sie zB brauchen os.getcwd()undos.path.isfile()
Nick T
15

Endgültige Antwort: import osund verwenden os.path. nicht import os.pathdirekt.

Aus der Dokumentation des Moduls selbst:

>>> import os
>>> help(os.path)
...
Instead of importing this module directly, import os and refer to
this module as os.path.  The "os.path" name is an alias for this
module on Posix systems; on other systems (e.g. Mac, Windows),
os.path provides the same operations in a manner specific to that
platform, and is an alias to another module (e.g. macpath, ntpath).
...
Lesmana
quelle
13
Beachten Sie, dass es sich nicht um Dokumente für ein os.pathModul handelt, das nicht vorhanden ist, sondern für posixpath.
wRAR
18
So denke ich überhaupt nicht, dass Docstring interpretiert werden soll, obwohl es ziemlich irreführend ist. Beachten Sie, dass der Satz "Instead of importing this module directly, import os and refer to this module as os.path."befindet sich in posixpath.py(oder macpath.py, ntpath.pyetc.). Ich bin mir ziemlich sicher, dass sie bedeuten, dass man import posixpathdas Modul nicht (was funktioniert) über importieren sollte, osum eine bessere Portabilität zu erreichen. Ich glaube nicht, dass sie eine Empfehlung geben wollen, ob sie bevorzugt werden import osoder nicht import os.path.
Flornbeben
1
Ich stimme den meisten Kommentaren von @flornquake zu, stimme aber dem letzten Satz nicht zu. Sowohl posixpath.py als auch ntpath.py sagen "import os und bezeichnen dieses Modul als os.path". Sie sagen nicht "os.path importieren und dieses Modul als os.path bezeichnen". macpath.py hat nichts damit zu tun.
Pete Forman
3
Dies ist ein gutes Beispiel dafür, wie ein Dokument, das diesen Zeiger enthält, irreführend sein kann: D
Cyker
7

Interessanterweise werden beim Importieren von os.path alle Betriebssysteme importiert. Versuchen Sie Folgendes in der interaktiven Eingabeaufforderung:

import os.path
dir(os)

Das Ergebnis ist das gleiche, als hätten Sie gerade das Betriebssystem importiert. Dies liegt daran, dass os.path je nach Betriebssystem auf ein anderes Modul verweist. Python importiert daher os, um zu bestimmen, welches Modul für den Pfad geladen werden soll.

Referenz

Bei einigen Modulen wird das Sprichwort import foonicht angezeigt foo.bar, daher hängt es wohl wirklich vom Design des jeweiligen Moduls ab.


Im Allgemeinen sollte der Import der benötigten expliziten Module geringfügig schneller sein. Auf meiner Maschine:

import os.path: 7.54285810068e-06 Sekunden

import os: 9.21904878972e-06 Sekunden

Diese Zeiten sind nahe genug, um vernachlässigbar zu sein. Ihr Programm muss möglicherweise ab ossofort oder zu einem späteren Zeitpunkt andere Module verwenden. Daher ist es normalerweise sinnvoll, nur die zwei Mikrosekunden zu opfern und import osdiesen Fehler zu einem späteren Zeitpunkt zu vermeiden. Normalerweise importiere ich nur das Betriebssystem als Ganzes, kann aber sehen, warum einige es vorziehen import os.path, technisch effizienter zu sein und den Lesern des Codes zu vermitteln, dass dies der einzige Teil des osModuls ist, der verwendet werden muss. Es läuft im Wesentlichen auf eine Stilfrage in meinem Kopf hinaus.

Matt Boehm
quelle
2
from os import pathmacht die Aufrufe zum Pfad noch schneller, wenn Geschwindigkeit das Problem ist.
Justin Peel
Explizit ist explizit besser als implizit, oder? In Wirklichkeit denke ich, dass es wirklich der Urteilsruf des Benutzers ist, ob der Benutzer nur os.path oder mehrere Module innerhalb von os verwenden wird. Vielleicht entspricht eine Methode eher Ihrer Philosophie als die andere?
Andrew Kou
23
Das Timing ist eine der vorzeitigsten vorzeitigen Optimierungen, die ich je gesehen habe. Das hat noch nie jemand den Engpass und die Zeit hier ist unerheblich, wie jemand Code sollte.
Mike Graham
5

Der gesunde Menschenverstand funktioniert hier: osist ein Modul und os.pathist auch ein Modul. Importieren Sie einfach das Modul, das Sie verwenden möchten:

  • Wenn Sie Funktionen im osModul verwenden möchten , importieren Sie os.

  • Wenn Sie Funktionen im os.pathModul verwenden möchten , importieren Sie os.path.

  • Wenn Sie Funktionen in beiden Modulen verwenden möchten, importieren Sie beide Module:

    import os
    import os.path

Als Referenz:

Cyker
quelle
4

Es konnte keine endgültige Referenz gefunden werden, aber ich sehe, dass der Beispielcode für os.walk os.path verwendet, aber nur os importiert

Chris Hulan
quelle