Seite 1 von 2
Namen des "Eltern"-Moduls herausfinden
Verfasst: Sonntag 7. September 2008, 12:00
von snafu
Hallo!
Ich glaube, die Bezeichnung Eltern-Modul passt nicht ganz, eignete sich aber imho ganz gut für eine prägnante Überschrift.
Zur Frage: Ich habe Modul
test2. Dieses Modul wird durch das Skript
test3 importiert. Nun soll mir test2 den Namen des Skriptes anzeigen, welches test2 importiert (in dem Fall ist der Name also test3). Wie bekomme ich das hin? Mit
print __name__ kann ich ja lediglich den Namen, des Moduls anzeigen, indem sich der besagte Befehl befindet. Ich hingegen möchte aber den Namen des - wie ich es nenne - Eltern-Moduls haben.
Ich hoffe man versteht was ich meine.
Gruß
Sebastian
Nochmal zur Veranschaulichung:
test2:
test3:
Ausgabe im Interpreter:
Es soll aber stattdessen
test3 ausgegeben werden.
Verfasst: Sonntag 7. September 2008, 12:42
von BlackJack
Warum willst Du wissen welches Modul das Modul als erstes importiert hat? So etwas sollte ein Modul nicht wissen (wollen).
Verfasst: Sonntag 7. September 2008, 13:09
von lunar
Code: Alles auswählen
import inspect
frame = inspect.currentframe().f_back
calling_mod_name = frame.f_globals['__name__']
print calling_mod_name
Verfasst: Sonntag 7. September 2008, 13:17
von snafu
BlackJack hat geschrieben:Warum willst Du wissen welches Modul das Modul als erstes importiert hat? So etwas sollte ein Modul nicht wissen (wollen).
Das geht auf meine kürzlich gestellte Frage zu __import__ zurück. Ich fing gestern an, etwas zu schreiben, das 3rd Party Module auf Existenz beim User überprüft, weil es mich einfach stört, für jedes einzelne fehlende Modul eine gesonderte Fehlermeldung zu bekommen. In meinem Docstring (Code folgt gleich) versuche ich, das ganze etwas ausführlicher zu erklären.
Bisher muss jedenfalls gesondert angegeben werden, welche Module überprüft werden sollen. Ich will aber jetzt implementieren, dass mein Modul in einem Sript aufgerufen wird und dann die import Befehle des Skriptes durchgeht, also die angegebenen Module checkt.
http://paste.pocoo.org/show/84651/
Verfasst: Sonntag 7. September 2008, 13:28
von lunar
Wofür braucht man sowas? Wenn man etwas programmiert, sollte man wissen, welche Module man verwendet, und die schreibt man dann in die setup.py oder in die README.
Verfasst: Sonntag 7. September 2008, 13:42
von Leonidas
Ich würde es aber eher über Import-Hooks lösen, so wie demandimport in Mercurial das macht.
Verfasst: Sonntag 7. September 2008, 13:43
von BlackJack
@snafu: Ich habe immer noch nicht verstanden wozu ein Modul dafür wissen muss, von welchem anderen es das erste mal importiert wurde!?
Der Rückgabewert von `findMissing()` sollte immer eine Liste sein. Sonst muss man ja immer explizit testen ob man nun eine Liste bekommen hat, mit der man etwas machen kann, oder `None`.
Verfasst: Sonntag 7. September 2008, 13:48
von snafu
lunar hat geschrieben:Code: Alles auswählen
import inspect
frame = inspect.currentframe().f_back
calling_mod_name = frame.f_globals['__name__']
print calling_mod_name
Super, danke dir.

Verfasst: Sonntag 7. September 2008, 13:50
von snafu
lunar hat geschrieben:Wofür braucht man sowas? Wenn man etwas programmiert, sollte man wissen, welche Module man verwendet, und die schreibt man dann in die setup.py oder in die README.
Okay, so rum vielleicht schon. Aber was ist mit Quelltext, den man aus irgendwelchen Foren oder Blogs übernimmt? Ich habe schon öfter erlebt, dass da nicht immer explizit dabei steht, was möglicherweise dazu installiert werden muss.
Verfasst: Sonntag 7. September 2008, 13:52
von sea-live
geht das ganze auch mit Funktionen
wo in welchem modul oder datei steckt das write
drin
Code: Alles auswählen
def _start(self):
self.bus.write( sda=1, scl=1 )
self.bus.write( sda=0, scl=1 )
self.bus.write( sda=0, scl=0 )
Verfasst: Sonntag 7. September 2008, 14:03
von snafu
BlackJack hat geschrieben:@snafu: Ich habe immer noch nicht verstanden wozu ein Modul dafür wissen muss, von welchem anderen es das erste mal importiert wurde!?
Weil es wissen muss, von welcher Datei es die Import-Lines prüfen soll.
BlackJack hat geschrieben:Der Rückgabewert von `findMissing()` sollte immer eine Liste sein. Sonst muss man ja immer explizit testen ob man nun eine Liste bekommen hat, mit der man etwas machen kann, oder `None`.
Ich dachte eigentlich an sowas:
Code: Alles auswählen
missing = modcheck.findMissing('BeautifulSoup', 'mechanize')
if missing:
print 'Es fehlen ein oder mehrere Module:'
for mod in missing:
print mod
Verfasst: Sonntag 7. September 2008, 14:21
von BlackJack
@snafu: Sorry, ich hab's immer noch nicht verstanden. Welches Modul muss wann, warum wissen von wem es das erste mal importiert wurde, bzw. wird!? Erklär's doch mal an einem Beispiel wo das irgendwie von nutzen ist.
Zum zweiten Punkt: Genau *so* kann man das auch verwenden wenn immer eine Liste zurückgegeben wird.
Verfasst: Sonntag 7. September 2008, 15:17
von snafu
BlackJack hat geschrieben:@snafu: Sorry, ich hab's immer noch nicht verstanden. Welches Modul muss wann, warum wissen von wem es das erste mal importiert wurde, bzw. wird!? Erklär's doch mal an einem Beispiel wo das irgendwie von nutzen ist.
Ich möchte die Möglichkeit bieten, dass man sich bspw. ein Skript aus dem Internet kopiert (wie gerade beschrieben) und dann als erste Zeile sowas einfügt, eigentlich fast genau so wie im Beispielcode davor:
Code: Alles auswählen
import modcheck, sys
missing = modcheck.checkFile(checkCaller=True)
usw, siehe oben
sys.exit(2) bei fehlenden Modulen
Er soll dann halt kurz alle verwendeten Module im fremden Skript prüfen und meckern wenn was fehlt. Warum du die ganze Zeit vom "ersten Mal importieren" sprichst, verstehe ich irgendwie selber nicht ganz. Es geht einfach nur um den "Caller", dessen Code bei dieser Option geparst werden soll.
BlackJack hat geschrieben:Zum zweiten Punkt: Genau *so* kann man das auch verwenden wenn immer eine Liste zurückgegeben wird.
Auch wenn None zurückgegeben wird, funktioniert der Code bei mir wunderbar.
PS: Zu checkFile, welches ich gerade dazugeschrieben habe:
Code: Alles auswählen
def checkFile(filename=None, checkCaller=False):
'''checkFile(filename=None, checkCaller=False)
Parse all import-lines in the script specified by filename and then call
findMissing() with the detected module names.
Set checkCaller=True if you want to check the script that imports modcheck.
'''
if checkCaller == True:
filename = inspect.currentframe().f_back.f_globals['__name__']
print filename
# the rest is not yet implemented
Verfasst: Sonntag 7. September 2008, 15:42
von Leonidas
snafu hat geschrieben:BlackJack hat geschrieben:Zum zweiten Punkt: Genau *so* kann man das auch verwenden wenn immer eine Liste zurückgegeben wird.
Auch wenn None zurückgegeben wird, funktioniert der Code bei mir wunderbar.
Ja, aber mit einer leeren Liste kann man mit for zugreifen ohne vorherige Prüfung und es kracht nicht. Letztendlich hättest du mit None einen Sonderfall:
Das ist so als würdest du jemanden bitten, dir 2 Apfel zu geben, also bekommst du eine Liste mit Zwei Äpfeln. Wenn du 0 Äpfel willst, würdest du der Konsistenz halber eine Liste der Länge null erwarten und nicht den "Kein-Apfel"-Apfel, oder?
Verfasst: Sonntag 7. September 2008, 15:57
von snafu
Achso, ok. Dann änder ich das. Ich dachte nur, das es nett ist, auf findMissing die Antwort "keine" zu bekommen. Aber nagut...
Verfasst: Sonntag 7. September 2008, 16:19
von BlackJack
@snafu: Das ist alles viel zu viel Magie. Das heraufhangeln des Framestack zum Beispiel sollte nicht in Produktivcode verwendet werden. Es gibt auch eine entsprechende Warnung im Docstring der Funktion. Das ist was für die Fehlersuche oder wenn man einen Debugger schreiben will.
Vom ersten mal importieren habe ich immer gesprochen weil Du *ursprünglich* wissen wolltest von wo Dein Modul importiert wird. Der Quelltext im Modul wird aber nur ausgeführt, wenn es *das erste mal* importiert wird. Jetzt hast Du Deine Anforderungen plötzlich geändert und möchtest wissen von welchem Modul aus eine Funktion aufgerufen wird. Das ist ja nun etwas anderes, weil man das natürlich öfter machen kann. Aber wie gesagt nicht sollte.
Und es funktioniert halt einfach nicht. Beispiel: Das Modul `spam` existiert nicht:
Code: Alles auswählen
import modcheck, sys
missing = modcheck.check_file(check_caller=True)
if missing:
print '...'
import spam, eggs
In der ersten Zeile wird Dein `modcheck` importiert. Dann wird die `check_file()`-Funktion aufgerufen, die das aufrufende Modul importiert. Da das *der zweite* ``import``ist , passiert gar nix. Wenn die `check_file()` zurück kehrt kommen wir nach dem ``if`` zum ``import spam, eggs`` und da kracht es dann ganz normal, also so wie Du das nicht haben möchtest, und ohne das Dein Modul irgend etwas gebracht hätte.
Mir ist aber auch nicht ganz klar wie Du in der `check_file()` mehr als einen Importfehler erkennen können willst!? Denn auch da könntest Du mit einem ``except ImportError`` ja nur den ersten Fehler abfangen.
Verfasst: Sonntag 7. September 2008, 18:15
von lunar
snafu hat geschrieben:lunar hat geschrieben:Code: Alles auswählen
import inspect
frame = inspect.currentframe().f_back
calling_mod_name = frame.f_globals['__name__']
print calling_mod_name
Super, danke dir.

Dir ist aber schon klar, dass sowas nichts in Produktivcode zu suchen hat?
Verfasst: Sonntag 7. September 2008, 20:06
von snafu
BlackJack hat geschrieben:Code: Alles auswählen
import modcheck, sys
missing = modcheck.check_file(check_caller=True)
if missing:
print '...'
import spam, eggs
In der ersten Zeile wird Dein `modcheck` importiert. Dann wird die `check_file()`-Funktion aufgerufen, die das aufrufende Modul importiert. Da das *der zweite* ``import``ist , passiert gar nix.
check_file() soll nicht das aufrufende Modul importieren, sondern die Funktion soll herausfinden, welche weiteren Module innerhalb des aufrufenden Moduls verwendet werden und diese testen.
Und dass man dies nich im Produktivcode verwenden soll, wusste ich nicht. Habe inspect.currentframe.__doc__ vorher nicht gelesen. Warum soll das denn nicht verwendet werden?
Verfasst: Sonntag 7. September 2008, 20:15
von lunar
snafu hat geschrieben:Und dass man dies nich im Produktivcode verwenden soll, wusste ich nicht. Habe inspect.currentframe.__doc__ vorher nicht gelesen. Warum soll das denn nicht verwendet werden?
Weil es tiefe Magie ist, unleserlich und unwartbar ist, und je nach Situation zu mysteriösen Fehlern führen kann. Es ist schlicht und einfach "kein guter Code".
Verfasst: Sonntag 7. September 2008, 20:34
von BlackJack
@snafu: Wie willst Du denn herausfinden welche anderen Module innerhalb eines Moduls verwendet werden? Ohne das Modul auszuführen!?
Code: Alles auswählen
try:
import psyco
psyco.full()
except ImportError:
pass
try:
from lxml import etree
except ImportError:
try:
from xml.etree import ElementTree as etree
except ImportError:
from elementtree import ElementTree as etree
if 'linux' in sys.platform:
from linux_specific import foobar
else:
def foobar():
import zzz
zzz.bla()
Welche Module werden hier importiert? Welche davon werden zwingend gebraucht? Wie sieht Dein Code aus, *das* heraus zu finden!? Viel Spass.
