Warum importieren Python-Module manchmal ihre Untermodule nicht?

87

Mir ist heute etwas Seltsames aufgefallen, das ich gerne erklären würde. Ich war mir nicht 100% sicher, wie ich das überhaupt als Frage formulieren sollte, also kommt Google nicht in Frage. Das Protokollierungsmodul hat aus irgendeinem Grund keinen Zugriff auf die Modul-Protokollierungshandler. Probieren Sie es selbst aus, wenn Sie mir nicht glauben:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

Kann jemand erklären, warum das passiert?

chriscauley
quelle

Antworten:

118

In Python müssen Module importiert werden, bevor auf sie zugegriffen werden kann. import loggingImportiert nur das Protokollierungsmodul. Es kommt also vor, dass logginges sich um ein Paket mit Submodulen handelt, aber diese Submodule werden immer noch nicht automatisch geladen. Sie müssen also explizit importieren, logging.handlersbevor Sie darauf zugreifen können.

Wenn Sie sich fragen, warum es so aussieht, als ob Sie diese zusätzlichen Importe manchmal nicht benötigen: Einige Pakete importieren einige oder alle ihrer Submodule, wenn sie importiert werden - einfach indem Sie diese Importe in ihre __init__.pyDateien ausführen. In anderen Fällen kann es sein, dass etwas anderes, das Sie importieren, ebenfalls importiert wird logging.handlers. Es spielt keine Rolle, welcher Code den Import ausführt. Solange etwas in Ihrem Prozess importiert wird, logging.handlersbevor Sie darauf zugreifen, ist es dort. Und manchmal ist ein Modul, das wie ein Paket aussieht, wirklich keines, wie osund os.path. osist kein Paket, es importiert nur das richtige andere Modul (für Ihre Plattform) und ruft es auf path, nur damit Sie als darauf zugreifen können os.path.

Thomas Wouters
quelle
4

Ich bin auch neu in Python und nachdem ich viel geübt habe, kann ich jetzt zwischen Paket (Ordner), Modul (.py), Klassen, Variablen ... usw. unterscheiden.

Wenn Sie möchten, dass einer Ihrer Ordner ein Python-Paket ist, muss er eine __init__.pyDatei enthalten , auch eine leere Datei reicht aus !!!

und wie Thomas sagte, können Sie zusätzliches Modul in __init__.py importieren, wenn Sie wollen !!! Module / Pakete sind jedoch erst nach dem Import zugänglich ...

Wenn Sie alles aus einem Modul importieren möchten, können Sie verwenden

from logging import *

Übrigens können Sie auch wie unten beschrieben auf das Handler-Modul zugreifen.

from logging import handlers
print dir(handlers)

shahjapan
quelle
5
Bitte nicht verwenden from module import * . Es ist fast immer ein Fehler.
Thomas Wouters
Wenn Sie möchten, dass alles in einem Paket automatisch importiert wird, führen Sie diese Importe in init durch .py durch, anstatt alles in init .py festzulegen und irgendwo 'from package import *' auszuführen.
Thomas Wouters
2
@Pete: weil es den Standard-Namespace "verschmutzt", was zu Mehrdeutigkeiten und Konflikten führt. Wenn ich hätte import zipperund zipper.open()Sie genau wissen würden, welches Open ich anrufe. Umgekehrtfrom zipper import * gefolgt von open()es ist die eingebaute in offenen oder zipper.open oder sonst etwas. import zipper as zwird sehr bevorzugt, wenn Sie müde vom Tippen werdenzipper
msw
3
@Pete: Es ist auch ein Problem, weil Sie möglicherweise einen Teil Ihres Namespace unwissentlich überschreiben. Ich habe früher von verwendetnumpy import * weil einige numpy-Funktionen nur funktionieren, wenn Sie alle numpy importieren (schrecklicher Designfehler von ihrer Seite IMO), aber numpy hat eine RIESIGE Anzahl von Objekten, die es importiert. Am Ende habe ich viele Funktionen überschrieben (ich glaube, Kopie war eine ... ich bin zu müde, um das zu überprüfen). Jetzt importiere ich numpy als np, wenn ich numpy so oft verwenden möchte, dass ich es nicht ertragen kann, es immer wieder zu tippen.
Chriscauley
2
@dustynachos, welche Numpy-Funktion hat diesen Fehler?
Winston Ewert
2

Thomas Wouters hat diese Frage sehr gut beantwortet, aber leider habe ich diese Frage erst gefunden, nachdem ich die Antwort in der Originaldokumentation gefunden hatte. Zu diesem Zweck dachte ich, ich würde dies in der Hoffnung ergänzen, dass es in Zukunft näher an der Spitze der Suchmaschine auftaucht.

FRAGE

Warum tritt der Fehler auf: ' AttributeError: Modul' Modulname 'hat kein Attribut' Submodulname ', obwohl mein Editor (z. B. Visual Code) den Submodulnamen automatisch vervollständigt:

 import module_name
 module_name.sub_module_name(parameter)

ANTWORTEN

Ihr Editor basiert seine automatische Vervollständigung auf der Dateistruktur Ihres Projekts und nicht auf dem Python-Verhalten. Untermodule werden beim Importieren eines Moduls nicht automatisch importiert. In der Python-Dokumentation finden Sie Details zum automatischen Importieren von Submodulen bei Verwendung

 import module_name

Der Hauptbeitrag zu dieser Antwort ist das Hinzufügen von AttributeError beim Versuch, ein 'Modul' oder 'Paket' zu importieren.

Hoffe das hilft jemandem!

Unterlauf
quelle
1

Ich habe in letzter Zeit die gleiche seltsame Situation erlebt. Ich wette, Sie haben einen Lib-Import von Drittanbietern entfernt. Das entfernte lib enthielt from logging import handlersoder from logging import *und stellte Sie zur Verfügung handlers. Und in anderen Skripten hatten Sie so etwas wie import loggingund haben es gerade benutzt, logging.handlersund Sie haben gedacht, dass die Dinge so funktionieren wie ich.

Alexey
quelle