In der Tat ist das Verhalten von __import__()
ausschließlich auf die Implementierung der import
Anweisung zurückzuführen, die aufruft __import__()
. Es gibt im Grunde fünf leicht unterschiedliche Weise __import__()
können aufgerufen werden import
(mit zwei Hauptkategorien):
import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
Im ersten und zweiten Fall sollte die import
Anweisung das Modulobjekt "ganz links" dem Namen "ganz links" zuweisen : pkg
. Nachdem import pkg.mod
Sie dies tun können, pkg.mod.func()
weil die import
Anweisung den lokalen Namen eingeführt hat pkg
, der ein Modulobjekt ist, das ein mod
Attribut hat. Die __import__()
Funktion muss also das Modulobjekt "ganz links" zurückgeben, damit es zugewiesen werden kann pkg
. Diese beiden Importanweisungen bedeuten also:
pkg = __import__('pkg')
pkg = __import__('pkg.mod')
Im dritten, vierten und fünften Fall muss die import
Anweisung mehr Arbeit leisten: Sie muss (möglicherweise) mehreren Namen zuweisen, die sie vom Modulobjekt erhalten muss. Die __import__()
Funktion kann nur ein Objekt zurückgeben, und es gibt keinen wirklichen Grund, jeden dieser Namen aus dem Modulobjekt abzurufen (und dies würde die Implementierung viel komplizierter machen). Der einfache Ansatz wäre also ungefähr so (für den dritten) Fall):
tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
Dies funktioniert jedoch nicht, wenn pkg
es sich um ein Paket handelt und / mod
oder mod2
um Module in diesem Paket , die nicht bereits importiert wurden , wie dies im dritten und fünften Fall der Fall ist. Die __import__()
Funktion muss das wissen mod
und mod2
sind Namen, auf die die import
Anweisung zugreifen soll, damit sie sehen kann, ob es sich um Module handelt, und versucht, sie auch zu importieren. Der Anruf ist also näher an:
tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
was bewirkt , dass __import__()
und Last , um zu versuchen pkg.mod
und pkg.mod2
sowie pkg
(aber wenn mod
oder mod2
nicht existieren, es ist nicht ein Fehler in dem __import__()
Aufruf, einen Fehler erzeugen, das den blieb import
. statement) Aber das ist noch nicht das Richtige für die vierten und fünftes Beispiel, denn wenn der Anruf so wäre:
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
Dann tmp
wäre es pkg
wie zuvor und nicht das pkg.mod
Modul, von dem Sie das submod
Attribut erhalten möchten . Die Implementierung hätte sich dafür entscheiden können, damit die import
Anweisung zusätzliche Arbeit leistet, den Paketnamen aufteilt, .
wie es die __import__()
Funktion bereits tut, und die Namen durchläuft, aber dies hätte bedeutet, einen Teil des Aufwands zu duplizieren. Anstatt also, macht die Umsetzung __import__()
Rückkehr die am weitesten rechts stehenden Modul anstelle des am weitesten links ein , wenn und nur wenn fromlist geben wird und nicht leeren.
(Die Syntax import pkg as p
und from pkg import mod as m
ändert nichts an dieser Geschichte, außer den lokalen Namen, denen zugewiesen wird. Die __import__()
Funktion sieht bei Verwendung nichts anderes as
aus, alles bleibt in der import
Anweisungsimplementierung.)