eval() in schleifen

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.
Leonard
User
Beiträge: 15
Registriert: Freitag 26. Dezember 2008, 15:01

Freitag 26. Dezember 2008, 15:23

Hallo
Ich habe ein Programm geschrieben, dass aus trigonometrische Funktionen, mit dem Modul PIL, ein Bild aus Spektralfarben erzeugt. Dazu muss für jeden einzelnen Pixel der Funktionswert errechnen werden, was im Prinzip kein Problem ist. Jedoch will ich gerne, dass man den Funktionsterm im Programm eingeben kann und genau das ist das Problem: die Funktion eval() ist einfach zu langsam. Bei einer Auflösung von 400 * 400 Pixeln muss eval() schon 160.000 mal verwendet werden. Gibt es eine Möglichkeit nur einmal eval() anzuwenden und dann damit weiter zu arbeiten, schließlich verändert sich der Funktionsterm nicht.

hier das Programm:

Code: Alles auswählen

# -*- coding: cp1252 -*-
from Tkinter import *
import Tix
from math    import *
from time    import *
from PIL import Image

class Funktionsplotter:
    def __init__(self,root):
        root.resizable(False,False)
        root.title("Funktionsplotter2.0")

        self.setTerm("cos(radians(sqrt(x**2+z**2)))")
        self.setXStart(-360)
        self.setXEnde(360)
        self.setZStart(-360)
        self.setZEnde(360)
        self.setBreite(400)
        self.setHoehe(400)
        
        self.__addWIDGETS()

        self.funktionsTerm.insert(0,self.getTerm())
        self.xStart.insert(0,self.getXStart())
        self.xEnde.insert(0,self.getXEnde())
        self.zStart.insert(0,self.getZStart())
        self.zEnde.insert(0,self.getZEnde())
        self.breite.insert(0,self.getBreite())
        self.hoehe.insert(0,self.getHoehe())
    #SET METHODEN
    def setTerm(self,pTerm):
        self.__zTerm=pTerm
    def setXStart(self,pXStart):
        self.__zXStart=int(pXStart)
    def setXEnde(self,pXEnde):
        if self.getXStart()<int(pXEnde):
            self.__zXEnde=int(pXEnde)
    def setZStart(self,pZStart):
        self.__zZStart=int(pZStart)
    def setZEnde(self,pZEnde):
        if self.getZStart()<int(pZEnde):
            self.__zZEnde=int(pZEnde)
    def setBreite(self,pBreite):
        self.__zBreite=int(pBreite)
    def setHoehe(self,pHoehe):
        self.__zHoehe=int(pHoehe)
    #GET METHODEN
    def getTerm(self):
        return self.__zTerm
    def getXStart(self):
        return self.__zXStart
    def getXEnde(self):
        return self.__zXEnde
    def getZStart(self):
        return self.__zZStart
    def getZEnde(self):
        return self.__zZEnde
    def getBreite(self):
        return self.__zBreite
    def getHoehe(self):
        return self.__zHoehe
    def getXIntervall(self):
        lTemp=float((self.getXEnde()-self.getXStart()))/float(self.getBreite())
        return lTemp
    def getZIntervall(self):
        lTemp=float((self.getZEnde()-self.getZStart()))/float(self.getHoehe())
        return lTemp
    
    def __addWIDGETS(self):
        distanz =2#padx,pady für frame
        distanz2=1#für restliche komponenten
        self.frame=Label(root)
        self.frame.grid(column=0,row=1,padx=2,sticky=N+E+S+W)
        #Labels + Frames
        funktionstermFrame=LabelFrame(self.frame,text=" Funktionsterm ")
        funktionstermFrame.grid(column=0,row=0,columnspan=2,padx=distanz,pady=distanz,sticky=N+E+S+W)
        label=Label(funktionstermFrame,text="f(x,z)=")
        label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
        
        wertebereichFrame=LabelFrame(self.frame,text=" Wertebereich in cm ")
        wertebereichFrame.grid(column=0,row=1,padx=distanz,pady=distanz,sticky=N+E+S+W)
        label=Label(wertebereichFrame,text="  X:  von ")
        label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
        label=Label(wertebereichFrame,text="  Z:  von ")
        label.grid(column=0,row=1,padx=distanz2,pady=distanz2)
        label=Label(wertebereichFrame,text="   bis   ")
        label.grid(column=2,row=0,padx=distanz2,pady=distanz2)
        label=Label(wertebereichFrame,text="   bis   ")
        label.grid(column=2,row=1,padx=distanz2,pady=distanz2)
        
        aufloesungFrame=LabelFrame(self.frame,text=" Auflösung in Pixeln ")
        aufloesungFrame.grid(column=1,row=1,padx=distanz,pady=distanz,sticky=N+E+S+W)
        label=Label(aufloesungFrame,text="  Breite: ")
        label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
        label=Label(aufloesungFrame,text="  Höhe:   ")
        label.grid(column=0,row=1,padx=distanz2,pady=distanz2)
        #Entrys
        self.funktionsTerm=Entry(funktionstermFrame,width=41)
        self.funktionsTerm.grid(column=1,row=0,padx=distanz2,pady=distanz2)
        
        self.xStart=Entry(wertebereichFrame,width=7)
        self.xStart.grid(column=1,row=0,padx=distanz2,pady=distanz2)
        self.xEnde =Entry(wertebereichFrame,width=7)
        self.xEnde.grid(column=3,row=0,padx=distanz2,pady=distanz2)
        self.zStart=Entry(wertebereichFrame,width=7)
        self.zStart.grid(column=1,row=1,padx=distanz2,pady=distanz2)
        self.zEnde =Entry(wertebereichFrame,width=7)
        self.zEnde.grid(column=3,row=1,padx=distanz2,pady=distanz2)

        self.breite=Entry(aufloesungFrame,width=7)
        self.breite.grid(column=1,row=0,padx=distanz2,pady=distanz2)
        self.hoehe=Entry(aufloesungFrame,width=7)
        self.hoehe.grid(column=1,row=1,padx=distanz2,pady=distanz2)
        #Buttons
        self.exportButton=Button(self.frame,text="Exportieren",command=self.export)
        self.exportButton.grid(column=0,row=3,columnspan=2,padx=distanz2,pady=distanz2,sticky=N+E+S+W)
        
    def export(self):
        self.exportButton.config(state=DISABLED)
        self.ladeBalken=Tix.Meter(self.frame,relief=FLAT,width=304,height=5,bd=0,fillcolor="blue")
        self.ladeBalken.grid(column=0,row=4,columnspan=2,sticky=N+E+S+W)
        start=time()
        
        self.setTerm(self.funktionsTerm.get())
        self.setXStart(self.xStart.get())
        self.setXEnde(self.xEnde.get())
        self.setZStart(self.zStart.get())
        self.setZEnde(self.zEnde.get())
        self.setBreite(self.breite.get())
        self.setHoehe(self.hoehe.get())
        
        self.pic = Image.new("RGB", (self.getBreite(),self.getHoehe()))
        
        self.xz2rgb()

        self.pic.save("f(x,z).jpg", "JPEG")
        ende=time()
        self.ladeBalken.destroy()
        self.exportButton.config(state=NORMAL)
        
        print "Exportdauer:",round(ende-start,5),"[sec]\nfür",self.getBreite()*self.getHoehe(),"Pixel"
    def xz2rgb(self):
        for h in range(self.getBreite()):
            x=self.getXStart()+h*self.getXIntervall()
            prozent=(float(100)/self.getBreite()*h+1)/100
            self.ladeBalken.config(value=prozent)
            self.ladeBalken.update()
            for v in range(self.getHoehe()):
                z=self.getZStart()+v*self.getZIntervall()
                y=eval(self.getTerm())
                self.pic.putpixel((h,v),(self.getFarbe(y)))
    def getFarbe(self,y):
        i=0.00196
        x=int(y/i)
        
        if 255<x<=510:
            r=255
            g=510-x
            b=0
        elif 0<x<=255:
            r=x
            g=255
            b=0
        elif -255<x<=0:
            r=0
            g=255
            b=abs(x)
        elif -510<=x<=-255:
            r=0
            g=510+x
            b=255
        else:
            r=0
            g=0
            b=0
        return r,g,b          
root=Tix.Tk()
funktionsplotter=Funktionsplotter(root)
root.mainloop()
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Freitag 26. Dezember 2008, 15:41

Guck dir mal compile an.

btw: Aus welchem Buch/Tut lernst du eigentlich Python?
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Freitag 26. Dezember 2008, 15:46

Lass die Sternchen Importe weg, beache PEP 8 und lass simple getter und setter weg und benutzt statt dessen properties sollte dies notwendig sein. Das dürfte die Chancen (brauchbare) Antworten zu bekommen drastisch steigen lassen.

Mach aus dem eingegebenen Code eine echte Funktion mit lambda, dass dürfte dass ganze etwas beschleunigen.
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Freitag 26. Dezember 2008, 15:50

mach aus dem eval eine lokale Referenz, anstatt jedes mal die globale zu verwenden. Das sollte auch etwas an Speed reibringen. Beispiel:

Code: Alles auswählen

def test():
    ev = eval
    for i in range(10000):
        ev(irgendwas)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 26. Dezember 2008, 16:19

Persönlich finde ich, dass ``eval()`` ein großer Schmarrn ist. Ich würde warscheinlich mit Pyparsing oder ähnlichem einen Parser für Formeln schreiben, diese Formeln in einen ``_ast``-kompatiblen AST schreiben, und diesen dann mit ``compile()`` in ein Code-Pbjekt kompilieren. Somit kann der User nix kaputtmachen, selbst wenn er es wollte, und der User hat mehr Freiheit beim Eingeben der Formeln (``3x`` geht in Python ja so nicht, etc, etc).
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 13:54

Hallo Leonard!

Versuchs mal damit:

Code: Alles auswählen

>>> f = eval("lambda x: x**2")
>>> f(3)
9
Statt den String mit y=eval("x**2") direkt auszuwerten kannst du ja auch mit obigen code eine Funktion erzeugen. Diese wird dann genau so schnell ausgewertet wie jede normale andere Funktion auch. Damit brauchst du auch nur ein eval. Zudem könntest du sicherlich deinen code noch weiter beschleunigen wenn du dann sowas wie numpy.fromfunction benutzt um dein Bild zu erzeugen.

@leonidas: Das ist eine der Gründe warum ich eval liebe :D. Ich finde es ist eines der wertvollsten und wichtigsten Sprachelemente überhaupt.

MFG HerrHagen
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 27. Dezember 2008, 14:28

:shock:

Äh, was spricht gegen das hier?

Code: Alles auswählen

>>> f = lambda x: x ** 2
>>> f(3)
9
Man braucht also gar kein eval().
@leonidas: Das ist eine der Gründe warum ich eval liebe Very Happy. Ich finde es ist eines der wertvollsten und wichtigsten Sprachelemente überhaupt.
eval() interpretiert nur einen String als Python Code! Das kannst du nur dann funktionierend und "sinnvoll" anwenden, wenn du diesen String auf umständliche Art und Weise generierst. Das ist fehleranfällig und resultiert in schwer zu durchschauendem Code, da du gewissermassen eine Programm in einem Programm baucst. Zusätzlich ist ein solcher Code 1. in kleinen Anwendungen einfahc un unnötig (wie von dir gezeigt) und 2. bei größeren Anwendungen absolut wartungsresistent, wodurch die Fehlersuche zur Gänsejagd wird, insbesondere dann, wenn man den String im Verlauf des Programmes immer mehr erweitert (oder ähnlich damit verfährt). Auch kann in einen solchen String von außen durch bloße Anwendung der Anwendung theoretisch Code eingefügt werden, wenn man Variablen zur Codegenerierung benutzt. Kurz, es wird sehr oft vor eval gewarnt ("eval is evil"), und ich kenne keinen einzigen Fall der akzeptablen Nutzung von eval() (aber ich habe schon einige grauenvolle Anwendungen gesehen, wennauch nicht in Python).
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Samstag 27. Dezember 2008, 15:04

HerrHagen hat geschrieben:Ich finde es ist eines der wertvollsten und wichtigsten Sprachelemente überhaupt.
Eval ist total überflüssig, i.d.R. immer nur eine behelfslösung weil man zu faul ist eine brauchbare Lösung umzusetzen aber selbst dann sollte man die Eingabe wenigstens validieren.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 15:37

Äh, was spricht gegen das hier?
So wie ich die Sache verstanden hab, ging es darum aus einer Benutzereingabe einen String mit der Funktion zu nehmen und diese dann zu plotten.
Ein einfaches lambda scheidet somit aus.
Kurz, es wird sehr oft vor eval gewarnt ("eval is evil")
Diese Warnungen kommen doch nur von neidischen C-Programmierern die ein eval bitter vermissen :wink:. Klar kann man mit eval viel Mist machen, aber das kann man mit jedem anderem Sprachelement auch (lambda, if, ...). Ich halte es für ein ganz elementares Sprachelement.
ich kenne keinen einzigen Fall der akzeptablen Nutzung von eval()
Da widerspreche ich. Der obige Fall ist doch schon ziemlich sinnvoll. Ich glaube kaum das irgendeine Syntaxparsing-Geschichte sehr viel übersichtlicher wäre.
Ich hab noch ein anderes Beispiel. Ich setzte eval zur Steuerung eines Mess-Moduls einer Industrie-Maschine ein. Maschine und Modul sind über Ethernet verbunden. Von der Maschine können Befehle an das Modul geschickt werden (starte Messvorgang,...). Statt eine Nummer o.Ä. für die entsprechende Funktion zu verschicken, sende ich einfache einen String mit dem Befehl. Dies hat folgende Vorteile:
  • - ich hab keine Redundanz mehr drin. Wenn ich bspw. einen Funktionsnamen ändere, brauch ich wirklich nur diesen einen Namen ändern und nicht zusätzlich das Parsing des Befehls. Das ganze wird so viiielll kürzer und übersichtlicher
  • - ich kann schnell mal was ausprobieren. Ich sende einfach ein größeres Paket an Befehlen und schau ob es funktioniert. Das ganze kann ich dann später ordentlich direkt implementieren
  • - ich kann schnell mal was debuggen. Ich sende einfach den Befehl, dass mir der Wert einer bestimmten Variable geschickt werden soll (dazu braucht man ja auch noch mal eval :wink:). Das ist wichtig, da das Modul nur einen IPC ohne Bildschirm hat.
Dabei muss ich noch erwähnen, dass das ganze natürlich nicht mit dem Internet oder überhaupt irgendwas anderem verbunden ist, so dass eine böse Person Schabernack mit gefährlichen Behlen treiben könnte.

MFG HerrHagen
lunar

Samstag 27. Dezember 2008, 17:20

Ich kenne deine Situation nicht, daher bin ich geneigt anzunehmen, dass du dir den Einsatz von eval gut überlegt hast, und mit bestem Wissen und Gewissen auf Alternativen wie xmlrpc und pyro verzichtet hast.

Dann allerdings wäre diese Situation einer der wenigen Sonderfälle, in denen eval oder Codegenerierung im Allgemeinen sinnvoll ist.

Die Tatsache, dass eval unter bestimmten Umständen sinnvoll oder akzeptabel ist, macht es aber noch lange nicht zu einem essentiellen Sprachmittel. Nichts für ungut, aber ein Python-Entwickler, der eval() für ein elementares Sprachelement hält, hat Python nicht kapiert.

Es gibt eine Sprache, bei der viele Entwickler eval() für ein elementares Sprachmittel halten: PHP. Wohin das geführt hat, ist ja bekannt ...

In dieser speziellen Situation halte ich ein eval für den ersten Entwurf für akzeptabel. Ein sauber entwickeltes Programm dagegen nutzt einen Parser und erzeugt daraus einen Ast. Das hat zwei Gründe: Zum einen gibt es so eine klare Spezifikation der erlaubten Sprache, und somit auch die Möglichkeit, gefährliche oder unsinnige Dinge im Interesse des Nutzers zu verbieten. Zum anderen kann man die Sprache so auf ihren Zweck zuschneiden. Ein Ausdruck der Art "2x" ist in Python ungültig, für die Eingabe mathematischer Formel dagegen ist es in höchstem Maße angenehm, wenn man nicht jede Multiplikation mit einem Operator hinterlegen muss.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Samstag 27. Dezember 2008, 17:39

Statt eine Nummer o.Ä. für die entsprechende Funktion zu verschicken, sende ich einfache einen String mit dem Befehl.
Also machst du grundsätzlich das hier:

Code: Alles auswählen

def do_that(string):
    eval(string)

do_that("first(arg); second()")
? Warum dann nicht gleich so:

Code: Alles auswählen

def do_that(function):
    function()

def function_we_need():
     first(arg)
     second()

do_that(function_we_need)
Zumindest hört sich dein Problem danach an.
BlackJack

Samstag 27. Dezember 2008, 17:52

@HerrHagen: Ich möchte mich lunar anschliessen: `eval()` ist kein elementares Sprachmittel in Python. Python bietet so viele Möglichkeiten der introspektion und dynamisch Objekte zu erzeugen, dass die gerechtfertigten Einsatzmöglichkeiten von `eval()` verschwindend gering sind. Gerechtfertig ist IMHO nur was mit der Sprache nicht machbar ist. Denn wenn man Quelltext generiert, ist das in der Regel ein Zeichen dafür, dass die Sprache an der Stelle nicht ausdrucksstark genug ist.

Zu Deinem Programm: Schau Dir an wie es das `cmd`-Modul macht. Wenn man das mit dem `shlex`-Modul verbindet um die Argumente zu parsen, kann man auch ohne `eval()` einen flexiblem Kommandointerpreter ohne viel Redundanz bauen.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 18:19

Die Tatsache, dass eval unter bestimmten Umständen sinnvoll oder akzeptabel ist, macht es aber noch lange nicht zu einem essentiellen Sprachmittel. Nichts für ungut, aber ein Python-Entwickler, der eval() für ein elementares Sprachelement hält, hat Python nicht kapiert.
Ich verneine das und behaupte das Gegenteil. :wink:
Das hat zwei Gründe: Zum einen gibt es so eine klare Spezifikation der erlaubten Sprache, und somit auch die Möglichkeit, gefährliche oder unsinnige Dinge im Interesse des Nutzers zu verbieten.
Eine Spezifikation der Sprache findest du unter python.org. Einen Interpreter für der dort beschriebenen Sprache ebenfalls. Warum sollte man einen Parser bauen und das Ergebnis dann interpretieren wenn es so etwas schon gibt.
Deine Argumentation stützt sich also im wesentlichen darauf, dass ein Benutzer ja etwas böses eingeben könnte was dann ausgeführt wird. Dies lässt aber all die Fälle vor, in denen dies nicht möglich ist oder keine Rolle spielt. Z.b. für eine Anwendung wie ich sie erwähnt hatte oder so etwas wie IDLE. Natürlich könnte der Benutzer etwas eingeben womit Daten von der Platte löscht. Das kann er aber auch einfacher haben indem er das einfach über das UI des Betriebsystems macht... Es gibt ja auch noch Anwendungen für Python außerhalb von Websites.

@BlackJack: Ich halte eval/exec für so wichtig, weil so eine neue Ebene von Möglichkeiten entsteht. Erzeugung von Code zur Laufzeit mag nicht so oft gefragt sein. ABER wenn dies der Fall ist, dann stehen schnell 5 Zeilen eval-Code 5000 Zeilen geparse entgegen.
Ich kenne die beiden Module. Ich weiß allerdings nicht warum ich sie benutzen soll wenns auch einfacher geht.

MFG HerrHagen
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 18:28

@str1442: Die Befehle kommen von "außerhalb" über Ethernet. Liegen also erstmal in str-form vor und können daher nicht direkt ausgeführt werden. Also eher statt:

Code: Alles auswählen

def func1: ...
def func2: ...
...

funcs = {'1': func1, '2':func2}
funcs[incoming_str]()
Mach ich:

Code: Alles auswählen

def func1: ...
def func2: ...
...

exec(incoming_str)
mit den oben beschriebenen Vorteilen aber auch Einschränkungen.
lunar

Samstag 27. Dezember 2008, 18:38

HerrHagen hat geschrieben:
Das hat zwei Gründe: Zum einen gibt es so eine klare Spezifikation der erlaubten Sprache, und somit auch die Möglichkeit, gefährliche oder unsinnige Dinge im Interesse des Nutzers zu verbieten.
Eine Spezifikation der Sprache findest du unter python.org. Einen Interpreter für der dort beschriebenen Sprache ebenfalls.
Der OP möchte keinen Python-Interpreter, sondern einen Interpreter für eine mathematisch sinnvolle Eingabesprache. Das ist nun mal nicht das Gleiche.

Diese Aussage lässt sich im Übrigen auf nahezu jede Anwendung von eval() vereinfachen.
Warum sollte man einen Parser bauen und das Ergebnis dann interpretieren wenn es so etwas schon gibt.
So?

Code: Alles auswählen

>>> x = 4
>>> eval('2 * x')
8
>>> eval('2x')
------------------------------------------------------------
   File "<string>", line 1
     2x
      ^
SyntaxError: unexpected EOF while parsing
Dir sollte bekannt sein, dass "2x" eine gängige mathematische Schreibweise ist, aber kein gültiger Python-Code.

Ein vernünftiger Parser erlaubt eine auf mathematische Bedürfnisse zugeschnittene Syntax in Verbindung mit einer besseren Fehlerbehandlung und der Beschränkung des Nutzers auf das tatsächliche Sinnvolle.
Deine Argumentation stützt sich also im wesentlichen darauf, dass ein Benutzer ja etwas böses eingeben könnte was dann ausgeführt wird.
Dann hast du meine Argumentation nicht verstanden. eval() ist nicht deswegen schlecht, weil es Sicherheitslücken auftut. Das ist zwar in machen Anwendungen relevant, aber bei weitem nicht in allen.

eval() ist vor allem deswegen schlecht, weil es in der Regel zu mies geschriebenen, unwartbaren Code führt, der eine miese Fehlerbehandlung hat (wenn überhaupt), schlecht zu lesen ist, und meist nicht im geringsten dokumentiert oder spezifiziert. Dazu kommt noch, dass er in den meisten Fällen schlicht kaputt ist, weil schon an so einfachen Aufgaben wie der Maskierung von Zeichenketten scheitert. Es gibt Ausnahmen, aber die bestätigen ja im Allgemeinen nur die Regel.

Wenn du durch die PHP-Anspielung auf das Argument Sicherheit gekommen bist, so hast du diese Anspielung missverstanden bzw. nicht viel Erfahrung mit PHP.

In PHP wird eval für alles mögliche genutzt. Das fängt bei der dynamischen Erzeugung von Typen an und hört eigentlich nie auf. Ich habe schon Sortier- und Suchalgorithmen gesehen, die intern eval() genutzt haben. Das hat natürlich negative Auswirkungen auf die Sicherheit, aber schlimmer sind eigentlich die negativen Auswirkungen auf Les- und Wartbarkeit des Codes.
Erzeugung von Code zur Laufzeit mag nicht so oft gefragt sein. ABER wenn dies der Fall ist, dann stehen schnell 5 Zeilen eval-Code 5000 Zeilen geparse entgegen.
Nenne mir einen einzigen Fall, bei dem Code-Erzeugung zur Laufzeit gebraucht wird, und der nicht durch andere Sprachmittel auszudrücken ist.

Btw, ich bezweifele, dass der eval-Code in deinem Projekt wesentlich kürzer ist als gleichwertiges mit xmlrpc oder pyro.
Antworten