动态定义sympy.abc变量:名称错误处理

时间:2015-10-14 10:56:24

标签: python error-handling sympy

我试图用eval SymPy表达式来评估,它可以包含任何abc字母:

from sympy.abc import *

我想在方法中实现一种通过动态定义相关变量来处理NameError的方法。这是它的要点

try:
    eval(expr)
except NameError as err:
    msg = str(err)
    pos = msg.find("'")
    letter = msg[pos+1]
    from sympy.abc import letter

很明显,sympy.abc中没有任何来信。这样会引发异常。另一个问题是,如果使用像theta这样的符号,那么只评估该符号的第一个字母。所以关于我如何能够首先设法导入字母值的任何提示,也许还可以处理像eta,phi等符号。

另一个重要问题是表达式中可能有许多不同的字母。我该怎么处理?

编辑:我已成功解决了这个问题。 以下是我的尝试:

def try_expr(expr):
    try:
        eval(expr)
    except NameError as err:
        msg = str(err)
        pos = msg.find("'")
        letter = msg[pos+1]
        pos = pos +1
        found = False
        while (pos+1 < len(msg)) and (not found):
            more = msg[pos+1]
            for symb in symbols:
                if more==symb or more.isdigit():
                    found = True
                    break
                if found is False:
                    letter = letter+more       
                    pos = pos + 1
        for alphabet in abc.__dict__:
            if letter == alphabet:
                exec('from sympy.abc import %s'%alphabet)
                letters.append(alphabet)
                try_expr(expr) # try to evaluate the expression again
import sympy.abc as abc
symbols = ['*','/','(',')',"'"]
letters = [] # for storing any letters that are in the expression
try_expr('2*theta')

我设法从sympy.abc导入了第一个未知变量(无论是单个字母还是像'theta'这样的希腊字母。但是,当我尝试递归调用该函数来查找任何其他未知数时,我设法导入的信件再次被提升为未知。在此过程中,我最终获得RuntimeError : maximum recursion depth exceeded while getting the str of an object

1 个答案:

答案 0 :(得分:0)

这是代码,带有运行示例

import sympy.abc as abc
symbols = ['*','/','(',')',"'",'"']
letters = []
def try_expr(expr):
    try:
        for letter in letters:
            exec('from sympy.abc import %s'%letter) # re-execute after finding each unknown variable
        l = expr.count('(')
        r = expr.count(')')
        if l == r:         
            eval(expr)
        elif l < r:
            eval((r-l)*'('+expr)
    except NameError as err:
        msg = str(err)
        pos = msg.find("'")
        letter = msg[pos+1]
        pos = pos +1
        found = False
        while (pos+1 < len(msg)) and (not found): # check for multi-char greek letters
            more = msg[pos+1]
            for symb in symbols:
                if more==symb or more.isdigit():
                    found = True
                    break
            if found is False:
                letter = letter+more       
                pos = pos + 1
        for alphabet in abc.__dict__:
            if letter == alphabet:
                letters.append(alphabet)
                try_expr(expr[expr.find(alphabet):]) # search for the next unknown variable

from sympy import sin, sqrt, log, exp, cos, tanh, sinh, cosh, atan, acos, asin
import sys
if len(sys.argv) == 1:
    expr = '(sin(x**2)-log(exp(2*y))) + cos(x**2) + a + b + c + theta*eta'
else:
    expr = sys.argv[1]
try_expr(expr)
for letter in letters:
    exec('from sympy.abc import %s'%letter)
print 'The SymPy expression %s contains the following letters : %s' %(eval('%s'%expr), letters)

编辑:在分割后对表达式进行评估时,为不平衡的paranthesis添加了修复程序。