I have a list of strings I need to parse to SymPy expressions. The problem is, if one of them raises a SympifyError exception, the following string will not return the same SymPy expression an identical string returned before the exception.
For example, the following code:
import traceback
from sympy.core import sympify
from sympy.core.evaluate import evaluate
from sympy.core.sympify import SympifyError
if __name__ == '__main__':
equations = ['Eq(sin(pi/6), x/10)', 'Eq(x, 3))', 'Eq(sin(pi/6), x/10)']
for equation in equations:
try:
with evaluate(False):
expr = sympify(equation)
print(expr)
except SympifyError:
traceback.print_exc()
outputs:
Traceback (most recent call last):
Eq(sin(pi/6), x/10)
File "C:\Users\vini_\Anaconda3\lib\site-packages\sympy\core\sympify.py", line 354, in sympify
Eq(sin(pi/6**1), x/10**1)
expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate)
File "C:\Users\vini_\Anaconda3\lib\site-packages\sympy\parsing\sympy_parser.py", line 889, in parse_expr
code = stringify_expr(s, local_dict, global_dict, transformations)
File "C:\Users\vini_\Anaconda3\lib\site-packages\sympy\parsing\sympy_parser.py", line 791, in stringify_expr
for toknum, tokval, _, _, _ in generate_tokens(input_code.readline):
File "C:\Users\vini_\Anaconda3\lib\site-packages\sympy\parsing\sympy_tokenize.py", line 384, in generate_tokens
raise TokenError("EOF in multi-line statement", (lnum, 0))
sympy.parsing.sympy_tokenize.TokenError: ('EOF in multi-line statement', (2, 0))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/vini_/PycharmProjects/bugfix_simpify/main.py", line 22, in <module>
expr = sympify(equation)
File "C:\Users\vini_\Anaconda3\lib\site-packages\sympy\core\sympify.py", line 356, in sympify
raise SympifyError('could not parse %r' % a, exc)
sympy.core.sympify.SympifyError: Sympify of expression 'could not parse 'Eq(x, 3))'' failed, because of exception being raised:
TokenError: ('EOF in multi-line statement', (2, 0))
Note that the first and third strings are identical, but their output is different (there's an additional **1
. The second one is intentionally incorrect (unbalanced parenthesis). I'm using the evaluate(False)
line because I need the expression to be as close as possible to the original string.
What am I doing wrong? Is there any way to fix it so that the output is the same for identical input strings?
Environment: Python 3.6.1; SymPy 1.1.1
Thanks in advance.
Your problem vanishes when I move the context manager evaluate
outside the try
–except
expression:
import traceback
from sympy.core import sympify
from sympy.core.evaluate import evaluate
from sympy.core.sympify import SympifyError
equations = ['Eq(sin(pi/6), x/10)', 'Eq(x, 3))', 'Eq(sin(pi/6), x/10)']
for equation in equations:
with evaluate(False):
try:
expr = sympify(equation)
except SympifyError:
traceback.print_exc()
else:
print(expr)
While this is something you probably should have done anyway (always put as little as possible in the try
clause), you should not have encountered this problem, which seems to be a bug – probably related to the context manager evaluate
not being properly closed.
Here is a much simpler script (obtained by reducing yours) producing a similar problem:
from sympy import sympify, evaluate
from sympy.abc import x,y
try:
with evaluate(False):
sympify(")")
except:
pass
(x+y).simplify()