Sympify返回相同输入的不同表达式

时间:2017-09-12 15:25:49

标签: python sympy symbolic-math

我有一个需要解析为SymPy表达式的字符串列表。问题是,如果其中一个引发了SympifyError异常,则以下字符串将不会返回相同的SymPy表达式,而是在异常之前返回相同的字符串。

例如,以下代码:

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()

输出:

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))

请注意,第一个和第三个字符串是相同的,但它们的输出是不同的(还有一个**1。第二个是故意不正确的(不平衡的括号)。我使用的是evaluate(False)行,因为我需要表达式尽可能接近原始字符串。

我做错了什么?有没有办法解决它,以便相同输入字符串的输出相同?

环境:Python 3.6.1; SymPy 1.1.1

提前致谢。

1 个答案:

答案 0 :(得分:0)

当我将上下文管理器evaluate移到try - except表达式之外时,您的问题就会消失:

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)

虽然这可能是你应该做的事情(总是尽可能少地放在try子句中),你不应该遇到这个问题,这似乎是一个错误 - 可能与上下文有关经理evaluate未正确关闭。 这是一个更简单的脚本(通过减少你的脚本获得)产生类似的问题:

from sympy import sympify, evaluate
from sympy.abc import x,y

try:
    with evaluate(False):
        sympify(")")
except:
    pass

(x+y).simplify()

I reported this bug