Alternative zu eval() ?

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.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich möchte, das ein User Daten eingeben kann, die aber nur vom Typ unicode, string, number, float, tuple, dict usw. sind.
In dem Fall eval() zu benutzten ist zwar nächstliegend, aber doof. Wie kann ich das anders machen???

btw. Der User kann die Daten über ein html Formular eingeben, aber das ist eigentlich egal.

EDIT: Doch noch was gefunden:
safe_eval: http://aspn.activestate.com/ASPN/Cookbo ... ipe/496746 - macht aber ehr eine blackliste... Ein versuch es mit einer whitelist zu probieren:
http://www.python-forum.de/post-45714.html#45714 - das schaue ich mir mal näher an...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

jens hat geschrieben:Ich möchte, das ein User Daten eingeben kann, die aber nur vom Typ unicode, string, number, float, tuple, dict usw. sind.
Würde dir da vielleicht ein JSON-Parser weiterhelfen? JSON kann doch eigentlich alles genannte, und das auch syntaktisch gleich zu python. (ok, unicodestrings nich, aber sofern du nicht "bytearrays" brauchst ist das doch sogar ein gewinn)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Gute Idee. Aber ich möchte erstmal bei der Python Syntax bleiben. Ich sollte das aber mal im Hinterkopf behalten...

Ich hab noch was gefunden: http://aspn.activestate.com/ASPN/Cookbo ... ipe/364469

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Du suchst nicht zufällig etwas zur Form-Validierung wie etwa WTForms?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ne, da nehme ich django's newforms ;)

Also um was es eigentlich geht: In PyLucid gibt es die "Preferences" Tabelle. Einstellungen, die Plugins und das Basis System hinterlegen können. Damit das ganze sehr flexibel ist, nutzte ich pickle... Bisher gibt es keine Möglichkeiten die Einstellungen zu verändern :(
Als erster Schritt, damit der Admin die Einstellungen bearbeiten kann, ist halt einfach alles mittels pprint in einer html Form editierbar zu machen. (Also pro Einstellung, ein Text-Input).
Auch wenn das nur der Admin darf, möchte ich aber ehr ungern eval() benutzen um die Eingaben in Python Objekte zu wandeln... Deswegen die Frage hier ;)

Auf langer Sicht gesehen, sollte ein Plugin allerdings newforms dafür nutzten, macht ja eigentlich auch mehr Sinn... Dennoch sollte es diese Form der editierbarkeit dennoch zusätzlich geben...

EDIT: Das ist daraus geworden:
http://pylucid.net:8080/pylucid/browser ... ta_eval.py

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich würde sowas so lösen, dass zu jedem Konfigurationswert, der z.B. in der Datenbank oder anderswo definiert ist, zugleich auch ein Typ und evtl. ein Default-Wert festgelegt sind. Möchte ein Benutzer einen Wert ändern, wird anhand des zugewiesenen Typs versucht, aus dem Eingabestring dieser Typ zu erzeugen. Klappt das, gut; wenn nicht, Fehlermeldung ausgeben. Deckt das nicht die von dir gewünschte Flexibilität ab?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Naja, ich muss da generell nochmal intensiver drüber nachdenken.

Evtl. gebe ich bei jedem Einstellungswert direkt auch den passenden newforms-Field an. Dann könnte man sehr einfach eine passende html-form mit Validierung erzeugen...

Am besten erstelle ich erstmal eine Liste mit potenziellen Einstellungswerten, um zu sehen, was überhaupt i.d.R. gespeichert werde muß...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Auch wenn ich es vielleicht nicht brauchen werde, hab ich in data_eval.py die Unterstützung für datetime und timedelta Einträge implementiert:

http://pylucid.net:8080/pylucid/changeset/1542

Keine Ahnung ob das die beste Variante ist, es zu implementieren, aber es funktioniert so und ist druch das dict ALLOWED_CALLABLES erweiterbar...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich würde dafür einen eigenen Parser schreiben. Ich habe 2x ein Microrahmenwerk für PEGs aka Parserkombinatoren gepostet, damit sollte das in 1-2 Stunden realisierbar sein.

Stefan
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Warum sollte ich mir einen eigenen Parser schreiben, wenn es compile schon für mich erledigt?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Weil eval() prinzipbedingt unsicher ist. Ich dachte, den auszuführenden Code könnten User eingeben. Da würde ich nur meinem eigenen Parser trauen.

Stefan
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hast du dir die sourcen überhaupt angesehen?
http://pylucid.net:8080/pylucid/browser ... ta_eval.py

Ich nutzte kein eval()

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Sollte es ast.py in die Stdlib schaffen kannst du "ast.literal_eval" nutzen: http://dev.pocoo.org/hg/sandbox/file/tip/ast/ast.py
TUFKAB – the user formerly known as blackbird
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich habe ehrlich gesagt, auf die Überschrift reagiert und das, was du in deinem ersten Posting von ASPN erwähnt hast, nicht deine fertige Lösung. In Google AppEngine-Zeiten würde ich ja empfehlen, nicht auf `import compiler` zu bauen. Warum enthält der UnitTest `testLineendings` eigentlich keine Asserts?

Stefan
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Die Sache schreit doch: Wenn man `eval()` benutzt, muss man einen verdammt guten Grund haben, und ich sehe hier keinen, im Gegenteil (User-Input). Also muss da was anderes her.

P.S.: Das hier bezieht sich ebenfalls auf den Titel und die ursprüngliche Frage. Nur, damit spätere Leser das nicht falsch verstehen können.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

sma hat geschrieben:Ich habe ehrlich gesagt, auf die Überschrift reagiert und das, was du in deinem ersten Posting von ASPN erwähnt hast, nicht deine fertige Lösung. In Google AppEngine-Zeiten würde ich ja empfehlen, nicht auf `import compiler` zu bauen. Warum enthält der UnitTest `testLineendings` eigentlich keine Asserts?
AppEngine saugt sowieso und _ast funktioniert auf der AppEngine mit ein wenig Hackery. Außerdem ist AppEngine sowas von weit weg von einer regulären Umgebung, dass du da nicht drauf achten musst außer du entwickelst speziell für die.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

So, hab das ganze nochmals uberdacht und neu implementiert... Ist aber noch nicht ganz fertig: http://pylucid.net:8080/pylucid/changeset/1544
Ich nutzte dann statt pickle mein data_eval um die Daten in der Datenbank abzulegen. Dafür kann der user aber dann einfach nur die newforms erzeuge html form ausfüllen. Da pickle quasi durch data_eval() ersetzt ist, kann nun ein User im django admin panel die Daten verändern...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten