Import-Fehler - no attribute - nach mv kein Fehler

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.
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Hallo Zusammen,

als Mitleser komme ich heute in die Verlegenheit mich anzumelden, um euch um Hilfe anzubetteln. Dieser Fehler macht mich so verrückt ich mache ALLES, damit er verschwindet. :D

Zum Problem:

Ich lade mir dynamisch ein Modul, z.B. pgignvxcfclamhx.py.

Die pgignvxcfclamhx.py sieht so aus:

Code: Alles auswählen

def func():
    a = 0
    for i in range(10):
        a = i + a
    return a
Und so wird sie geschrieben:

Code: Alles auswählen

tmpfile = open(filename,'w+')
tmpfile.write("def func():")
cf = open(codefile)
for line in cf:
	line = line.strip('\n')
	tmpfile.write("\n\t"+ line )
tmpfile.write("\n\treturn a"),tmpfile.close
cf.close
So lade ich das Modul.

Code: Alles auswählen

f,filename,desc = imp.find_module(fname,['/var/tmp/'])
module = imp.load_module(fname,f,filename,desc)
Wenn ich nun module.func() anfrage, dann:

Code: Alles auswählen

AttributeError: 'module' object has no attribute 'func'
Nun mache ich auf der Shell: mv pgignvxcfclamhx.py pgignvxcfclamhx1.py, sprich ändere nur den Namen, dann geht module.func().

Warum nur? Charset des files wird nicht geändert. Rechte sind auch gleich. Ist beim Schreiben des Files was falsch? Ich werde verückt.

Das gleiche passiert auch, wenn ich von der Shell aus python3 starte. Vor dem mv kommt der Fehler, nach dem mv wird brav 45 zurück gegeben.
Gruß
ttze
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Was sagt denn `dir(module)`?
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Vor mv:

Code: Alles auswählen

>>> dir(pgyeqwftuwoafm)
['__builtins__', '__doc__', '__file__', '__name__', '__package__']
dann:

Code: Alles auswählen

mv pgyeqwftuwoafm.py pgyeqwftuwoafm1.py

Code: Alles auswählen

>>> dir(pgyeqwftuwoafm1)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'func']
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Was sind denn deine Anforderungen an die Software? Bestimmt gibt es da eine vernünftigere Lösung, als Quelltext zu generieren und diesen dann einzubinden.

Außerdem schließt du die File-Objekte nicht, das ist vermutlich der Fehler

Code: Alles auswählen

fobj.close # !=
fobj.close()
Selbst wenn es damit funktioniert, scheint mir diese keine sinnvolle und elegante Lösung zu sein.

Ein Beispiel in Bezug auf Eleganz. Deine Beispielfunktion geht auch so:

Code: Alles auswählen

def func():
    return sum(xrange(10))
;)
BlackJack

Wäre ein einfaches ``return 45`` nicht *noch* eleganter? ;-)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

BlackJack hat geschrieben:Wäre ein einfaches ``return 45`` nicht *noch* eleganter? ;-)
Ich bin mal davon ausgegangen, dass er die magische ``10`` eventuell variabel haben will ;)
BlackJack

Na dann halt ``return (n**2 - n) // 2``, damit auch bei grossem `n` die Laufzeit nicht zu stark anwächst. :-P
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Als ich gestern Abend auf "Absenden" geklickt habe, war mir klar, dass es peinlich wird. :oops:

In der Tat habe ich die Klammern übersehen. Ein mv auf der Shell macht das close natürlich von selbst, somit ist geklärt warum das alles so passiert.

Sicher wäre ein return 45 eleganter, aber das ist nicht gewollt. Das ist ein spontan entstandenes Minimalbeispielt für eine Benutzereingabe. Im Rahmen meiner Abschlussarbeit versuche ich ein interaktives Schulungssystem für Python zu entwerfen. Das geht bestimmt alles eleganter, aber "im Rahmen seiner Möglichkeiten löste er die ihm gestellten Aufgaben..." :D

Vielen Dank für den Hinweis. Manchmal sieht man es einfach nicht.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Vielleicht bist du auch an meinem Funktionsparser interessiert:
http://paste.pocoo.org/show/145054/

aus folgendem Thread:
http://www.python-forum.de/viewtopic.php?p=147443&

Falls du interessiert bist, kann ich dir auch die aktuelle Version zukommen lassen. (Ist ein sehr kl. Teil meiner Studienarbeit...)

Edit: Falls dir nicht klar ist, was der Parser genau macht und zu was der gut ist, kann ich auch noch eine Beschreibung ausarbeiten. Muss ich eh noch machen ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ttze hat geschrieben:Im Rahmen meiner Abschlussarbeit versuche ich ein interaktives Schulungssystem für Python zu entwerfen.
Also wenn dort Codegenerierung verwendet wird, dann ist der Entwurf schlecht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Leonidas hat geschrieben: Also wenn dort Codegenerierung verwendet wird, dann ist der Entwurf schlecht.
Bitte was? Kannst du mir sagen, was genau du mit Codegenerierung meinst?
BlackJack

@ttze: Damit ist das erzeugen von Quelltext und schreiben in temporäre Dateien zum Ausführen gemeint.
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Und das der Entwurf schlecht ist, kann man mit den 15 Zeilen da oben erkennen? Na denn. :shock:
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

BlackJack hat geschrieben:@ttze: Damit ist das erzeugen von Quelltext und schreiben in temporäre Dateien zum Ausführen gemeint.
DAS ist immer schlecht, wie von mir auch schon erwähnt!
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Und warum?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Habe jetzt keinen Nerv um diese Zeit noch ein ausführliches Statement abzugeben. Kurz und knapp: Es gibt einfach keinen Grund, dieses Verfahren überhaupt einzusetzen. Es gibt elegantere und sicherere Methoden, um Benutzereingaben als Code(-teile) verarbeiten.
Wenn man schon Erfahrungen mit Software Engineering gesammelt hat (beachte auch den Unterschied zwischen Programmieren und SE), WEIß man einfach auch, dass diese Methodik ein schlechter Stil ist, da gibt es eigentlich auch nicht viel zu erklären...
ttze
User
Beiträge: 9
Registriert: Montag 9. November 2009, 21:47

Und anstatt einfach kurz ein elegantes Stichwort zu nennen, macht man sich lieber die Mühe von oben herab den Oberlehrer zu spielen, ohne nähere Infos zum Code zu haben. Zwei, drei Stichworte hätten es ja auch getan, dann hätte ich nochmal lesen können und alles wären glücklich. Das wäre hilfreich gewesen. Vielleicht muss ich die Eingaben ja irgendwie ablegen, weil ich mit zwei verschiedenen Anwendungen arbeite und leider keine Objekte hin und her werfen kann? Vielleicht weiss ich ja auch, dass eval etc böse ist und mir entsprechend Gedanken dazu gemacht habe.

Aber schön das die Nerds so reagieren, wie man es von ihnen erwartet. Selbstgerecht und zynisch. Sobald jemand mal mit Nichtwissen glänzt wird drauf gehauen. Und dabei habe ich nciht mal eine doofe Frage gestellt. Hier wird unaufgefordert rumbelehrt. Echt unnötg sowas. Schade, die Anmeldung hat sich nicht gelohnt.
BlackJack

@ttze: Also wenn ich mir zu `eval()` Gedanken mache, und Quelltext erzeugen, in eine Datei schreiben, und dann importieren anschaue, dann sehe ich die *selben* Probleme wie bei `eval()` plus ein paar weiterer, die man sich auf diese Weise einhandelt. Dann doch lieber `compile()`, `eval()` und/oder ``exec``.

Nochmal zum Quelltext: Das öffnen mit 'w+' löscht den alten Dateiinhalt nicht, das heisst, wenn es die Datei schon gibt, und weniger geschrieben wird, als vorher drin war, dann steht nach den neuen Daten immer noch alter "Müll", der zu Problemen führen kann.

In der Funktion steht ja schon ``return a`` und beim Generieren des Modulinhaltes schreibst Du diese Zeile noch einmal extra dahinter!?

Das hart kodierte `/var/tmp/` macht den Quelltext ziemlich systemabhängig. Das Modul `tempfile` aus der Standardbibliothek kann helfen plattformunabhängig temporäre Dateien und Verzeichnisse zu finden bzw. zu erzeugen.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

ttze hat geschrieben:Vielleicht muss ich die Eingaben ja irgendwie ablegen, weil ich mit zwei verschiedenen Anwendungen arbeite und leider keine Objekte hin und her werfen kann?
Warum soll IPC nicht gehen?
>> PIPES, Sockets, XML-RPC, SOAP, ..
(Ich versuche deine Kritik umzusetzen, hier hast du deine Stichworte ;) )

Außerdem müsstest bei deiner Lösung dem zweiten Prozess ja auch sagen, dass die Datei geschrieben ist.

Am besten beschreibst du auch mal deine konkreten Anforderungen, dann können wir dir bestimmt auch noch genauer helfen und dir entsprechende Stichworte geben. Bisher ist mir noch nicht ganz klar, was für Usereingaben du überhaupt hast und was für ein Code dabei herauskommen soll. Da müssen wir dann halt auch ein bisschen spekulieren und können nicht so konkret werden...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ttze hat geschrieben:Aber schön das die Nerds so reagieren, wie man es von ihnen erwartet. Selbstgerecht und zynisch. Sobald jemand mal mit Nichtwissen glänzt wird drauf gehauen.
Ich hocke halt nicht den ganzen Tag am Rechner, um auf Fragen zu antworten. Aber kauf doch Leonidas Premium, mit EMail und IRC-Support. Alternativ auch Leonidas Ultimate mit Telefonsupport. Spaß beseite...
ttze hat geschrieben:Und dabei habe ich nciht mal eine doofe Frage gestellt. Hier wird unaufgefordert rumbelehrt.
Ich hab halt nur nen Einwurf gemacht, weil ich nicht mehr Zeit hatte. Eine etwas ausfühlichere Erklrärung (ist auch schon spät, daher fasse ich mich kurz, ok?): Codegenerierung führt zu Code der schwer zu Debuggen ist und auch zu unnötiger Platten-IO. Außerdem wird durch das erstellen von Dateien und das laden dieser, der Code in Bytecode-kompiliert und nur einmal ausgeführt. Bei normalen Code wird einmal kompiliert und mehrmals ausgeführt, was ein wenig effizienter ist. Außerdem, stell dir vor, du arbeitest auf einem read-only-Dateiesystem oder einem wo du keine Schreibberechigungen hast. Oder das Dateisystem ist voll. Was dann? Das wäre ohne Codegenerierung nicht nötig, zudem es gerade in Python eigentlich immer elegantere und hübschere Lösungen gibt.
ttze hat geschrieben:Schade, die Anmeldung hat sich nicht gelohnt.
Du kannst von deinem 14-Tage Rücktrittsrecht Gebrauch machen und dein Geld zurückfordern. :P

Ich finds aber auch etwas seltsam dass sich niemand zu einer Erklärung erbarmt hat...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten