How can I (easily) take a string such as "sin(x)*x^2"
which might be entered by a user at runtime and produce a Python function that could be evaluated for any value of x
?
Python's own internal compiler can parse this, if you use Python notation.
If your change the notation slightly, you'll be happier.
import compiler
eq= "sin(x)*x**2"
ast= compiler.parse( eq )
You get an abstract syntax tree that you can work with.
eval("sin(x)*x**2")
after setting x
and using from math import *
. –
Ozonosphere eval()
not solve the problem? Can you explain what's missing? "evaluated for any value" seems to be covered by eval
. What's missing? –
Ozonosphere eval()
which I specifically tried to avoid putting in the answer. –
Ozonosphere import compiler
doesn't work with Python 3.3 Could you please update your answer + tags to make sure the reader know which one it is about. It's a good question and should have the relevant tags covered. –
Amphimixis compiler
module for python 3 is described here: #909592 –
Bijugate EDIT parser
is deprecated in Python 3.9: https://docs.python.org/3/whatsnew/3.9.html#new-parser
You can use Python parser
:
import parser
from math import sin
formula = "sin(x)*x**2"
code = parser.expr(formula).compile()
x = 10
print(eval(code))
It performs better than pure eval
and, of course, avoids code injection!
eval()
on user input can be very dangerous. –
Tableland formula = "os.system('format C:')"
:) –
Modernistic >>> eval(parser.expr("os.system('echo evil syscall')").compile())
evil syscall
–
Glidebomb f = parser.parse('sin(x)*x^2').to_pyfunc()
Where parser
could be defined using PLY, pyparsing, builtin tokenizer, parser, ast.
Don't use eval
on user input.
eval
on user input is indeed bad. –
Camion parser
module in Python 3.8 but it complains: Module 'parser' has no attribute 'parse'
–
Enchain parser
module). Here's an example for arithmetic expressions –
Vainglorious pyparsing might do what you want (http://pyparsing.wikispaces.com/) especially if the strings are from an untrusted source.
See also http://pyparsing.wikispaces.com/file/view/fourFn.py for a fairly full-featured calculator built with it.
To emphasize J.F. Sebastian's advice, 'eval' and even the 'compiler' solutions can be open to subtle security holes. How trustworthy is the input? With 'compiler' you can at least filter out things like getattr lookups from the AST, but I've found it's easier to use PLY or pyparsing for this sort of thing than it is to secure the result of letting Python help out.
Also, 'compiler' is clumsy and hard to use. It's deprecated and removed in 3.0. You should use the 'ast' module (added in 2.6, available in 2.5 as '_ast').
In agreement with vartec. I would use SymPy - in particular the lambdify function should do exactly what you want.
See: http://showmedo.com/videotutorials/video?name=7200080&fromSeriesID=720
for a very nice explanation of this.
Best wishes,
Sage is intended as matlab replacement and in intro videos it's demonstrated how similar to yours cases are handled. They seem to be supporting a wide range of approaches. Since the code is open-source you could browse and see for yourself how the authors handle such cases.
© 2022 - 2024 — McMap. All rights reserved.