Ungewöhnliche Namensraumverschmutzung beim Importieren von Submodulen in __init__.py eines Pakets

8

main.py:

%Vor%

Paket / __ init __. py:

%Vor%

Paket / foo.py:

%Vor%

Execute main.py wird wie folgt ausgeben:

%Vor%

Der import in __init__.py hat nicht wie erwartet funktioniert. Beachten Sie, dass der globale Namespace ein 'foo' hat, das nur an lokale 'mod'

binden soll

Sogar a %Code% kann nicht verhindern, dass der globale Namespace geändert wird

Wie konnte das passieren?

    
zhangyoufu 24.09.2012, 02:13
quelle

1 Antwort

3

Ah! Tricky, aber ich habe es!

"foo" ist kein einfaches "anderes Paket" - es scheint Python als ein Untermodul Ihres "Paket" -Moduls zu erscheinen.

Wenn Sie "package" zum ersten Mal ausführen - entweder aus einem externen Skript importieren oder mit der Befehlszeilenoption -m ausführen (aber nicht, wenn Sie python package/__init__.py direkt über die Befehlszeile ausführen), das Paket "Das Modul wird analysiert und zum sys.modules dictitionary (im Modul sys ) hinzugefügt.

Wenn das Untermodul foo gelesen wird, wird es nicht nur direkt unter sys.modules unter dem Schlüssel ["package.foo"] platziert, sondern auch als Attribut für das übergeordnete Modul. Daher wäre es in Ihrer Python-App als package.foo verfügbar. Was passiert, wenn das Setzen eines Attributs in sys.modules["package"] den gleichen Effekt hat wie das Setzen eines Schlüssels in package/__init__.py globals in Runtime. Das ist was passiert.

Ich hoffe, ich könnte den Prozess richtig in Worte fassen - wenn nicht, frage einfach nochmal nach kommentieren.

- Da dies wahrscheinlich in realem Code geschieht, den Sie haben, und das Äquivalent von "do_import" von Code außerhalb Ihres Pakets aufgerufen wird (und die Nebeneffekte hat, Ihre Untermodule im globalen Namespace des Pakets erscheinen zu lassen), gibt es kein einfaches Arbeite auf dem Weg herum, den du machst. Mein Vorschlag ist, nur einen Unterstrich ( _ ) am Anfang der Untermodulnamen hinzuzufügen, wenn sie nicht aus allgemeinem Code von außerhalb des Pakets aufgerufen werden sollen. (Es wird auch nicht angezeigt, wenn jemand from package import * in diesem Fall tut)

    
jsbueno 24.09.2012, 04:05
quelle

Tags und Links