44 Stimmen

Gleichungsanalyse in Python

Wie kann ich (einfach) eine Zeichenkette wie die folgende nehmen "sin(x)*x^2" die von einem Benutzer zur Laufzeit eingegeben werden und eine Python-Funktion erzeugen könnte, die für jeden Wert von x ?

53voto

S.Lott Punkte 371691

Pythons eigener interner Compiler kann dies analysieren, wenn Sie die Python-Notation verwenden.

Wenn Sie die Schreibweise leicht ändern, werden Sie zufriedener sein.

import compiler
eq= "sin(x)*x**2"
ast= compiler.parse( eq )

Sie erhalten einen abstrakten Syntaxbaum, mit dem Sie arbeiten können.

1 Stimmen

Können Sie einen Beispielcode für die Verwendung der abgeleiteten Funktion hinzufügen?

2 Stimmen

@Don: Sie brauchen den Syntaxbaum nicht zu verwenden. Verwenden Sie die ursprüngliche Funktion. eval("sin(x)*x**2") nach der Einstellung x und mit from math import * .

1 Stimmen

Eval() funktioniert, aber die Antwort löst das Problem nicht wirklich :(

34voto

Don Punkte 16053

Sie können Python verwenden parser :

import parser
from math import sin

formula = "sin(x)*x**2"
code = parser.expr(formula).compile()
x = 10
print(eval(code))

Sie ist besser als reine eval und vermeidet natürlich Code-Injection!

7 Stimmen

Ein wichtiger Punkt ist, dass die Verwendung reiner eval() auf Benutzereingaben können sein sehr gefährlich .

0 Stimmen

@devxeq Ich meine damit, dass es keine Dinge akzeptiert wie formula = "os.system('format C:')" :)

1 Stimmen

@Don Na gut. :)

15voto

jfs Punkte 370717
 f = parser.parse('sin(x)*x^2').to_pyfunc()

Wo parser könnte mit PLY, pyparsing, eingebautem Tokenizer, Parser, ast definiert werden.

Verwenden Sie nicht eval auf Benutzereingaben.

7 Stimmen

eval auf Benutzereingaben ist in der Tat schlecht.

0 Stimmen

Könnten Sie etwas genauer sein? Ich habe versucht zu importieren parser Modul in Python 3.8, aber es beschwert sich: Module 'parser' has no attribute 'parse'

0 Stimmen

@s.ouchene: "parser" steht hier nur für ein benutzerdefiniertes Modul, das die entsprechende Funktionalität implementiert (es ist nicht wörtlich stdlibs parser Modul). Hier ist ein Beispiel für arithmetische Ausdrücke

10voto

cryo Punkte 13701

Pyparsing könnte das tun, was Sie wollen ( http://pyparsing.wikispaces.com/ ), insbesondere wenn die Zeichenfolgen aus einer nicht vertrauenswürdigen Quelle stammen.

Siehe auch http://pyparsing.wikispaces.com/file/view/fourFn.py für einen ziemlich vollwertigen Rechner, der damit gebaut wurde.

0 Stimmen

Die Links sind nicht mehr auf wikispaces verfügbar.

2 Stimmen

Pyparsing wird nicht mehr auf wikispaces.com gehostet. Gehe zu github.com/pyparsing/pyparsing

3voto

Andrew Dalke Punkte 14207

Um J.F. Sebastians Ratschlag zu unterstreichen: "eval" und sogar die "Compiler"-Lösungen können für subtile Sicherheitslücken offen sein. Wie vertrauenswürdig ist die Eingabe? Mit 'compiler' kann man zumindest Dinge wie getattr-Lookups aus dem AST herausfiltern, aber ich habe festgestellt, dass es einfacher ist, PLY oder pyparsing für diese Art von Dingen zu verwenden, als das Ergebnis zu sichern, indem man Python aushelfen lässt.

Außerdem ist der Begriff "Compiler" unhandlich und schwer zu verwenden. Es ist veraltet und wird in 3.0 entfernt. Sie sollten das Modul "ast" verwenden (hinzugefügt in 2.6, verfügbar in 2.5 als "_ast").

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X