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.
Ravebaby
User
Beiträge: 14
Registriert: Donnerstag 24. Februar 2005, 10:32
Kontaktdaten:

Zu was ist denn bitteschön dieses eval() sinnvoll?!
Ich hab 2 Bücher daheim und mir x online Links angeschaut. Aber überall steht nich viel mehr als ein Satz dazu.

Soviel weiß ich bisher:
"eval wertet einen String aus, der ein Ausdruck sein muss. Damit können dynamisch erzeugte Anweisungen ausgeführt werden."
Was soll das heißen?
Das man mittels eval() einen String zu einer Liste konvertieren kann, hab ich schon verstanden. Aber sonst?

Irgendwo stand auch mal:
"Damit ist der Interpreter Bestandteil der Programmiersprache. Damit kann man im laufenden Programm Quelltext erzeugen und ausführen lassen."
Wie das?

Und es soll sicherheitstechnisch nicht ganz ungefährlich sein, weil es beliebigen Code ausführen kann.
Warum benutzt man es denn dann?

Und was bedeutet das:
"ohne eval wuerde es nur den namen der variablen, nicht deren inhalt ausgeben."

Weiß jemand mehr dazu?
Würde mir sehr weiterhelfen!!!
Danke!!
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Eval ist deswegen ein Teil des Interpreters, weil man eine String übergibt und dieser wie eine normale Anweisung ausgeführt wird, man kann also Python sagen: "Interpretiere mal schnell das hier und sag mir das Ergebniss, als würde es schon im Quelltext stehen"

Code: Alles auswählen

>>> x=1
>>> y=eval("x+1")
>>> y
2
>>> def f(x):
	return x**2

>>> print eval("f(y)")
4
>>> help(eval)
Help on built-in function eval in module __builtin__:

eval(...)
    eval(source[, globals[, locals]]) -> value
    
    Evaluate the source in the context of globals and locals.
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals must be a dictionary and locals can be any mappping,
    defaulting to the current globals and locals.
    If only globals is given, locals defaults to it.
Tja, und daraus sollte man erkennen können, das es möglich ist beliebige Strings zu übergeben. Diese Strings können z.T. während der Laufzeit erzeugt wurden sein und deswegen beliebigen (gültigen!!!) Code enthalten. Es gibt nur eine Einschränkung: es dürfen nur expressions übergeben werden und keine statements, Zuweisungen und Schleifen sind also nicht möglich. Dies ist mit exec möglich. Wozu es nützlich ist hab ich bis heute noch nicht entdeckt, da ich immer wieder andere Methoden gefunden habe, aber es ist gut zu wissen das es sowas gibt :wink:
Gast

hi,....

ich habe es verwendet um die eingabe in einer gui umzuwandeln. ich lege oft verschiedene typen mit pickle in einer textdatei ab,

Code: Alles auswählen

entry.get()
liefert einen string, um das ganze dann zu dem zu machen was ich wirklich brauche, habe ich eval benützt:

Code: Alles auswählen

>>> l="[2,3,5]"
>>> eval(l)
[2, 3, 5]
>>> 
wurde auch hier besprochen:


http://python.sandtner.org/viewtopic.php?t=2717



mfg

rolgal
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Und genau das ist dann eine Sicherheitslücke. Was, wenn jemand in das Entry rm -rf oder ähnliches einträgt?

Gruß, mawe
Gast

hi mawe!

stimmt, aber nachdem nur ich das programm verwende, habe ich mir bez. sicherheitslücken keine gedanken gemacht.

gibts ne andere möglichkeit?

mfg

rolgal
Gast

hm, am besten wäre wohl falsche einträge abzufangen, also nur jene zulassen die ein [,{ oder ( aufweisen, oder?

mfg


rolgal
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Nö. Am besten wäre es einen Parser zu schreiben der ohne eval arbeitet, denn bei dir geht sowas hier trotzdem:

Code: Alles auswählen

>>> eval("[sys.exit(1)]")

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in -toplevel-
    eval("[sys.exit(1)]")
  File "<string>", line 0, in -toplevel-
SystemExit: 1
Man kann natürlich auch os.system(...) schreiben, das wäre dann fatal. Deswegen benutze ich es auch nicht, da os in den allermeisten Fällen importiert ist...
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

<off topic>
Hi rolgal,

fürs pickling brauchst Du kein "eval". Es geht auch so:

Code: Alles auswählen

pickle.dump(data,open(path,'w'),protocol)
#und zurück mit
data = pickle.load(open(path))
Hierbei kann "data" alles Mögliche sein - auch eine liste. Das shelve-Modul verwendet ebenfalls pickle und auch da braucht es kein eval, um an die abgelegten Daten zu kommen.
Dann hast Du auch keine Sicherheitslücke, weil kein Ausdruck Deiner Daten an sich ausgeführt wird.

Gruß,
Christian
</off topic>
edit:
P.S. Oder Du nutzt, bei den Daten eines GUI geht das möglicherweise, das Snippet, daß ich heute morgen gepostet hatte ... Deine Daten können dabei auch ohne eval beliebig komplex sein.
Zuletzt geändert von CM am Donnerstag 24. Februar 2005, 13:25, insgesamt 2-mal geändert.
Gast

hi,...

danke für die antworten, guck mir das gleich mal in ruhe an!

mfg

rolgal
Ravebaby
User
Beiträge: 14
Registriert: Donnerstag 24. Februar 2005, 10:32
Kontaktdaten:

auch von mit ein fettes Dankeschön. Endlich kann ich mit dem eval() was anfangen *freu* :wink:
Gast

hi christian,....

habe mir auch dein snippet, interessantes beispiel, mir ist da etwas nicht klar:

Code: Alles auswählen

pickle.dump(self,open(fname,'w'),2)
entspricht dem hier, was du zuerst für mich gepostet hast:

Code: Alles auswählen

pickle.dump(data,open(path,'w'),protocol) 
was hat es mit dem protocol, also der 2 auf sich?

mfg

rolgal
Gast

hi christian,...

irgendwas funzt nicht, ich habe mal die 2 einfach übernommen:

Code: Alles auswählen

>>> data="[1,2,3]"
>>> import pickle

>>> pickle.dump(data,open('/home/rolgal/testpickle.txt','w',2))
>>> data = pickle.load(open('/home/rolgal/testpickle.txt'))
>>> data
'[1,2,3]'

aber da habe ich eben wieder einen string und keine liste :?:

mfg

rolgal
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi rolgal!

Wenn die Listen die Du eingibst immer flach sind (und mit , getrennt), kannst Du das versuchen:

Code: Alles auswählen

l = "[1,2,3]"
x = l.strip('"[]').split(',')
print x
Nich wirklich geistreich und sehr unflexibel, ich weiß, aber vielleicht kannst Du's brauchen :wink:

Gruß, mawe
Gast

hi mawe,...

danke mal für die anregung. aber ich gebe die unterschiedlichsten typen ein, was ist genau eine liste die nicht flach ist? wenn verschiedene typen in ihr enthalten sind? also z.b.

Code: Alles auswählen

l=[1,2,'text']
:?:

mfg
rolgal
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi rolgal!

Mit flach hab ich gemeint, nicht so

Code: Alles auswählen

[[1,2],[3,4]]
also nicht verschachtelt. Heisst das überhaupt so? Ich weiß nicht mal ob das andere flach heisst, wollte nur intelligent klingen :D

Gruß, mawe
Gast

hi mawe,...

alles klar, hauptsache ich weiss was du gemeint hast :D


was glaubst du bzw ihr: wenn ich

Code: Alles auswählen

eval()
verwende und teste ob '[', '{'' usw enthalten ist und innerhalb des typs kein oder stehen darf, ist es dann sicher genug? oder gibt es einfach zuviele andere anweisungen die dann noch schaden anrichten könnten?

mfg

rolgal
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

rolgal hat geschrieben:oder gibt es einfach zuviele andere anweisungen die dann noch schaden anrichten könnten?
Jop. Ich kann zum Beispiel über die Module popen2,subprocess,cgi und einige andere denselben schaden anrichten. Außerdem kann ja auch anderes importiert wurden sein, also das ist viel zu unsicher. Benutz eval nur, wenn du sicher bist, dass keine Informationen von woanders außerhalb des Programmes als Argumente eingeschleust werden können.
Gast

hi milan,

hast wohl recht, es kann zwar eigentlich nichts passieren bzw. sehr unwahrscheinlich wenn nur ich das programm verwende, aber es interessiert mich natürllich eine bessere lösung zu finden.

mal sehen, was sich noch ergibt

mfg

rolgal
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hi rolgal,

doch, schau mal genau hin: Mein Pseudo Code entspricht dem Code im Snippet: "protocol" kann Werte zwischen 0 und 2 annehmen. 0 ist ASCII, 1 entspricht einem binären Protokoll und 2 dem neuen binären Protokoll mit dem sich auch Newstyle-Klassen picklen lassen. Im Allgemeinen kann man ab Python 2.3 alle Protkolle verwenden (von Ausnahmen abgesehen). Protokoll 2 ergibt die stärkste Kompression.

Zu der Geschichte mit data = "[1,2,3]": Nun, hier gibst Du einen String und picklest diesen. Was Du herausbekommst ist ein String. Versuche mal eine Liste oder eine Klasseninstanz zu picklen ...

Tut mir leid, daß ich nicht eher geantwortet habe. Ging nicht anders. Schaue mal in die Doku - pickle habe ich auch erst so richtig zu schätzen gewußt als ich die ersten Beispiele gesehen habe.

Gruß,
Christian
Gast

hi christian,
doch, schau mal genau hin: Mein Pseudo Code entspricht dem Code im Snippet: "protocol" kann Werte zwischen 0 und 2 annehmen. 0 ist ASCII, 1 entspricht einem binären Protokoll und 2 dem neuen binären Protokoll mit dem sich auch Newstyle-Klassen picklen lassen. Im Allgemeinen kann man ab Python 2.3 alle Protkolle verwenden (von Ausnahmen abgesehen). Protokoll 2 ergibt die stärkste Kompression.
ok, verstehe ich so in etwa, aber


Zu der Geschichte mit data = "[1,2,3]": Nun, hier gibst Du einen String und picklest diesen. Was Du herausbekommst ist ein String. Versuche mal eine Liste oder eine Klasseninstanz zu picklen ...
ich will aber einen string, bzw. muss einen string picklen und brauche eine liste. vielleicht sitze ich ja auf der leitung :?: :?:


Tut mir leid, daß ich nicht eher geantwortet habe. Ging nicht anders. Schaue mal in die Doku - pickle habe ich auch erst so richtig zu schätzen gewußt als ich die ersten Beispiele gesehen habe.
kein problem, besteht ja keine verpflichtung zu antworten. zu pickle: ich finds es gut

mfg

rolgal
Antworten