Namen des "Eltern"-Moduls herausfinden

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.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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:

Code: Alles auswählen

print __name__
test3:

Code: Alles auswählen

import test2
Ausgabe im Interpreter:

Code: Alles auswählen

>>> import test3
test2
Es soll aber stattdessen test3 ausgegeben werden.
BlackJack

Warum willst Du wissen welches Modul das Modul als erstes importiert hat? So etwas sollte ein Modul nicht wissen (wollen).
lunar

Code: Alles auswählen

import inspect
frame = inspect.currentframe().f_back
calling_mod_name = frame.f_globals['__name__']
print calling_mod_name
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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/
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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich würde es aber eher über Import-Hooks lösen, so wie demandimport in Mercurial das macht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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`.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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. :)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
sea-live
User
Beiträge: 440
Registriert: Montag 18. Februar 2008, 12:24
Wohnort: RP

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 )
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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
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.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Achso, ok. Dann änder ich das. Ich dachte nur, das es nett ist, auf findMissing die Antwort "keine" zu bekommen. Aber nagut...
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.
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?
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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?
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".
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. :-)
Antworten