用Try节点替换Python调用AST节点



我使用的系统允许用户将Python布尔表达式指定为字符串(在配置文件中(。系统获取字符串,将其转换为Python AST对象,然后根据输入数据计算表达式。

偶尔会出现布尔表达式可能导致错误的情况(例如,输入数据的条目数量不正确(。要求是,如果用户将布尔表达式封装在fail_on_error(...)中,则会捕获异常并将其转换为False(例如(:

assert test('fail_on_error(True)') == True
assert test('fail_on_error(False)') == False
assert test('fail_on_error(list()[0])') == False # index out of range

这可以使用正则表达式来完成,解析表达式字符串,但我更喜欢使用";正确的方式";使用Python的CCD_ 3模块。不幸的是,我遇到了问题。

守则

class ReplaceWithTry(ast.NodeTransformer):
def visit_Call(self, node):
if node.func.id != 'fail_on_error':
return node
# Get (first) argument to 'fail_on_error' and return its evaluated expression
return_expr = ast.Return(value=node.args[0])
except_handler = ast.ExceptHandler(type=None,
name=None,
body=ast.Return(value=ast.NameConstant(value=False))])
return ast.Try(body=[return_expr],
handlers=[except_handler],
orelse=[],
finalbody=[])
def test(expr_str):
syntax_tree = ast.parse(expr_str, '<string>', 'eval')
new_tree = ast.fix_missing_locations(ReplaceWithTry().visit(syntax_tree))
ast_obj = compile(new_tree, '<string>', 'eval')
return eval(ast_obj)

错误

我得到以下错误:

knoepfel$ python replace_with_try.py 
Traceback (most recent call last):
File "replace_with_try.py", line 24, in <module>
assert test('fail_on_error(True)')
File "replace_with_try.py", line 21, in test
ast_obj = compile(new_tree, '<string>', 'eval')
TypeError: expected some sort of expr, but got <ast.Try object at 0x103da33a0>

显然我错过了什么。有什么想法吗?

这是一个很老的问题,但我想这将适用于

class ReplaceWithTry(ast.NodeTransformer):
def visit_Call(self, node):
if node.func.id != 'fail_on_error':
return node
new_node = ast.parse("""try: ...""") # your statement in python code
return new_node

def test(expr_str):
syntax_tree = ast.parse(expr_str)
new_tree = ast.fix_missing_locations(ReplaceWithTry().visit(syntax_tree))
ast_obj = compile(ast.unparse(new_tree), '<ast>', 'eval')
return eval(ast_obj)

最新更新