Direkter import und nochmal Teil-Import - Sinn? (Am Beispiel von gnome-tweaks)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
SnakeBite
User
Beiträge: 46
Registriert: Mittwoch 4. März 2009, 18:26

Hallo.

Ich hab mir in meinem Lernprozess einmal anderen Quellcode angesehen und es gibt etwas das ich nicht verstehe. Hier der Quellcode:

https://github.com/GNOME/gnome-tweaks/b ... k/utils.py

Zu beachten: Zeile 13 und 14.

Wenn er/sie eh schon mit "import gtweaks" den kompletten Folder importiert, wieso importiert er/sie dann in der nächsten Zeile nochmal ganz speziell mit "from gtweak.gsettings import GSettingsSetting".

Irgend etwas muss ich missverstehen. Importiert "import gtweaks" gar nicht den ganzen Ordner und alle darin befindlichen Dateien? Ist dies einfach um es nochmal extra zu verkürzen, so dass er nicht jedesmal "gtweak.gsettings.GSettingsSetting" tippen muss?

Irgendwas verstehe ich hier nicht. Bitte um Hilfe.

Vielen Dank!
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, ein Import aus einem Paket oder Modul importiert erstmal automatisch NICHT alles, was es an Untermodulen gibt.

Einfaches Beispiel aus der Standardbibliothek:

Code: Alles auswählen

>>> 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.7/logging/handlers.pyc'>

Man *kann* Pakete so schreiben, dass sie ihre Untermodule automatisch gleich mit importieren. Ein Beispiel dafuer ist das Modul os in der Standardbibliothek:

Code: Alles auswählen

>>> import os
>>> os.path
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>
Das ist aber explizit so gemacht & nicht immer eine gute Idee, weil es ggf. viele Dinge anzieht, die dann gar nicht gebraucht werden. Im Falle von os ist es aber bequemer, weil das so oft verwandt wird, und os.path ueberall benutzt wird.
SnakeBite
User
Beiträge: 46
Registriert: Mittwoch 4. März 2009, 18:26

Hmmm ich befürchte das verstehe ich nicht.

Was genau importiert denn der Befehl "import gtweaks" dann genau? gtweaks ist doch nur ein Ordner? Was bringt das?

Und aus Deinem Beispiel: Warum ist das so? Woher weiss ich dass import logging nicht Alles mitimportiert, import os allerdings schon? Einfach Trial and error? Finde ich ja nicht sonderlich gut. Wenn ich Alles an Logging haben will, dann will ich das mit einem "import logging" auch zur Verfügung haben. Wenn ich nur eine bestimmte Funktion will, kann ich es ja selbst mit "from loggin import XXX" spezifizieren. Was ist da der Sinn dahinter?
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du magst das finden wie du willst, aber so ist die Semantik nunmal. Und du liegst falsch, wenn du behauptest gtweaks ist "nur ein Ordner". Da wird die Datei gtweaks/__init__.py importiert, und was auch immer darin definiert wird, steht dir zur Verfuegung. Wenn darin die Zeile

import gtweaks.settings as settings

steht, oder wie in os https://github.com/python/cpython/blob/ ... /os.py#L57

import posixpath as path

dann steht dir das Modul unter os.path halt zur Verfuegung.

Und du liegst falsch wenn du glaubst, from logging import X wuerde NUR den Namen X einbinden! Da wird IMMER das ganze Modul logging importiert (wenn das das erste mal ist, sonst ist das Modul ja schon bekannt), und alles was dann passiert ist, dass du in deinem Namensraum halt nur X reinholst.

Grund fuer dieses Verhalten ist, das nicht rekursiv gigantische Modulmengen geladen werden. Bei den meisten Dingen waere das zu verschmerzen. Mach sowas mal py PyQt, und du wartest 10 Sekunden, bis was passiert. Da will man dann schon lieber Kontroller drueber.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`import gtweaks` importiert keinen Ordner sondern ein Modul. Wenn `gtweaks` ein Package ist, dann ist es das Modul das in `__init__.py` im `gtweaks`-Ordner liegt. Und importieren heisst, das Modul wird (beim ersten import) *ausgeführt*. Und bei diesem ausführen können halt auch weitere importe ausgeführt werden, wenn die Bestandteil des Codes im Modul sind. Zum Beispiel weil der Code in dem Modul etwas aus den Untermodulen benötigt.

Das `import os`-Beispiel ist nicht so gut weil `os` gar kein Package ist, und `path` demnach dort auch kein Untermodul ist. An `os.path` wird auch ein Modul gebunden, aber welches das ist, wird zur Laufzeit vom `os`-Modul bestimmt, und zwar anhand des Systems auf dem der Code ausgeführt wird. Ein `import os.path` funktioniert also gar nicht.

Ich würde sagen: Mach Dir einfach keine Gedanken ob ein Package Untermodule bereits selbst importiert, sondern importiere die explizit wenn Du etwas daraus brauchst. Wenn die bereits importiert waren, passiert ja nix schlimmes. So bist Du immer auf der sicheren Seite. Denn das jetzt etwas schon importiert wird, heisst ja nicht, dass es in folgenden Versionen auch so passieren muss. Da kann man dann nur durch eine Aktualisierung einer Bibliothek vermeidbare Fehler im eigenen Code bekommen.

Ganz unabhängig davon ist da ja auch die Frage der Namen und was man im eigenen Modul an Namen binden möchte, oder was man über Module referenzieren möchte. Denn selbst wenn `import gtweaks` alle Unterpakete und -module importieren würde, möchte man im eigenen Code ja vielleicht nicht immer `gtweak.gsettings.GSettingsSetting` schreiben wenn man das Objekt benutzen möchte, sondern einfach nur `GSettingsSetting`.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
SnakeBite
User
Beiträge: 46
Registriert: Mittwoch 4. März 2009, 18:26

Vielen Dank __blackjack__, schön langsam verstehe ich es besser.

Ich dachte "import XX" importiert einfach die komplette Datei namens XX.py. Dass "import XX" auch die __init__.py des Ordner "XX" importieren kann, wusste ich nicht.

Mit "import gtweaks" holt er sich also nur die Einstellungen aus der __init__.py ins Programm und die zweite Zeile ist dann der eigentlich Importvorgang, der auch "wirklich" was importiert.

Das habe ich verstanden. Top! Vielen Dank Dir!!
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hmjanee. Auch der erste import importiert "wirklich" was. Es obliegt den Paket-Autoren, *was* das ist. Im Falle von gtweak tatsaechlich fast nichts, aber sie koennten da auch schon jeden Menge Dinge einfuehren.
Antworten