2017-05-08 5 views
3

Ich hoffe, dass jemand Einblick in einige zusätzliche Namensbindungen geben kann, die Python3 während eines Imports erstellt. Hier ist der Testfall:Python - Unerwarteter Import Occuring

Ich erstellte ein Testpaket namens "Spam" (original, ich weiß). Es enthält 3 Dateien wie folgt:

enter image description here

Die Inhalte der Dateien sind wie folgt:

__init__.py:

from .foo import Foo 
from .bar import Bar 

foo.py:

def Foo(): 
    pass 

bar.py:

def Bar(): 
    pass 

Ziemlich einfache Sachen. Wenn ich das "Spam" -Paket importiere, kann ich sehen, dass es Namensbindungen zu den Foo() und Bar() Funktionen im 'spam'-Namespace erstellt, die erwartet wird. Was nicht erwartet wird ist, dass es auch einen Namen an die "foo" und "bar" Module im 'spam' Namespace bindet, wie unten gezeigt.

enter image description here

Was ist noch interessanter ist, dass diese zusätzlichen Namensbindungen an das Modul nicht auftreten, wenn ich die Foo() und Bar() Funktionen in Haupt importieren, wie unten dargestellt:

Lesen Sie die Dokumentation über die Import-Anweisung (Sprache Ref und Tutorial), ich sehe nichts, was dazu führen würde.

Kann jemand etwas beleuchten, warum, wenn eine Funktion von einem Modul in einem Paket importiert wird, es auch einen Namen an das Modul bindet, das die Funktion enthält?

Antwort

0

Ja - das ist richtig und Teil des Python-Import-Mechanismus.

Wenn Sie ein Modul eine Menge Dinge passieren importieren, aber wir können auf ein paar konzentrieren:

1) Python überprüft, ob das Modul bereits geladen ist - zu diesem Mittel, prüft sie, ob es qualifyed bane ist (Namen mit Punkten) unter sys.modules

2) Wenn nicht, ist es das Modul tatsächlich geladen: die Überprüfung für vorkompilierte gecached Bytecode-Dateien enthält, analysiert, kompiliert die .py Datei sonst usw ...

3) Es macht tatsächlich die Namen Bindungen wie sie in der import Befehl sind: das heißt "von. Foo Import Foo" erstellt eine Variable " Foo "im aktuellen Namespace, der auf das Objekt" spam.foo.Foo "verweist.

Beachten Sie, dass das Modul immer als Ganzes geladen - und im Wörterbuch sys.modules zugeordnet ist. Außerdem stellt der Importprozess alle Untermodule zu einem Paket in dem Modulnamensraum zur Verfügung, der in diesem Paket sichtbar ist - das ist der Grund, warum die Namen "foo" und "bar" in Ihrem Spam-Paket sichtbar sind.

Sie könnten am Ende Ihrer __init__.py Datei die Namen „foo“ und „bar“ löschen - aber das wird die Art und Weise erwartet Import und Verwendung von spam.foo arbeitet in funamental Wege brechen - im Grunde: sys.modules["spam.foo"] existieren wird, aber sys.modules["spam"].foo gewohnt - was bedeutet, dass nach man versucht zu tun:

import spam.foo 
spam.foo.Foo() 

Python einen Namen Fehler auf „foo“ ergeben.

Die Import-Maschine meldet es als vorhanden (es ist in sys.modules), so dass es nichts tut. Aber "spam.foo" wurde entfernt, so dass es nicht erreichbar ist.

+0

Danke für diese detaillierte Antwort. Ich fand es gut angelegt. Ich denke, dass das folgende Zitat es nagelt: * "Außerdem stellt der Importprozess alle Untermodule zu einem Paket im Modulnamenraum, der in diesem Paket sichtbar ist, her - das ist der Grund, warum die Namen" foo "und" bar "sichtbar sind in deinem Spam-Paket. "* Weißt du irgendeinen Platz in der Dokumentation, die das ausspricht? Oder haben Sie etwas gefunden, indem Sie den Quellcode gelesen haben? – MACS

Verwandte Themen