I'm using ast to get information from Python source files (as per the suggestion here). For this, I have extended ast.NodeVisitor
and it runs fine with most source files. However, I'm getting a
我正在使用ast从Python源文件中获取信息(根据此处的建议)。为此,我扩展了ast.NodeVisitor,它可以与大多数源文件一起运行。但是,我得到了一个
RuntimeError: maximum recursion depth exceeded while calling a Python object
exception when I use this on big classes (~2000 lines. Terrible practice. I know :) ). When I inspect the stack upon the crash, I see that there is indeed a very deep recursion going on, but it does not seem to be going in a loop. I.e., if the recursion would go on for some more, it'll complete successfully. Is there a way to fix this?
当我在大班上使用它时(约2000行。可怕的练习。我知道:))。当我在崩溃时检查堆栈时,我发现确实存在非常深的递归,但它似乎没有进入循环。即,如果递归将继续进行,它将成功完成。有没有办法来解决这个问题?
I'm not sure if this has anything to do with this, but this big class contains a large if ... elif ... elif ... elif ... else
statement.
我不确定这是否与此有任何关系,但这个大类包含一个大的if ... elif ... elif ... elif ... else语句。
2 个解决方案
#1
I met the error recently, I think this will help you:
我最近遇到了这个错误,我想这会对你有所帮助:
class MyNodeVisitor(ast.NodeVisitor):
def visit(self, node):
"""Visit a node, no recursively."""
for node in ast.walk(node):
method = 'visit_' + node.__class__.__name__
getattr(self, method, lambda x: x)(node)
#2
I figured it out: Since I only need to parse ClassDef
, Import
and FromImport
statements, I gave an overriding method to generic_visit
that does nothing:
我想通了:因为我只需要解析ClassDef,Import和FromImport语句,所以我给了generic_visit的一个重写方法,它什么都不做:
def generic_visit(self, node):
pass
instead of the super's generic_visit
, which was causing the recursion. This also boosted performance greatly. The downside is that only statements in the global scope of the module are parsed (I think), but that's fine with what I need.
而不是super的generic_visit,它导致了递归。这也极大地提升了性能。缺点是只解析模块全局范围内的语句(我认为),但这对我需要的很好。
#1
I met the error recently, I think this will help you:
我最近遇到了这个错误,我想这会对你有所帮助:
class MyNodeVisitor(ast.NodeVisitor):
def visit(self, node):
"""Visit a node, no recursively."""
for node in ast.walk(node):
method = 'visit_' + node.__class__.__name__
getattr(self, method, lambda x: x)(node)
#2
I figured it out: Since I only need to parse ClassDef
, Import
and FromImport
statements, I gave an overriding method to generic_visit
that does nothing:
我想通了:因为我只需要解析ClassDef,Import和FromImport语句,所以我给了generic_visit的一个重写方法,它什么都不做:
def generic_visit(self, node):
pass
instead of the super's generic_visit
, which was causing the recursion. This also boosted performance greatly. The downside is that only statements in the global scope of the module are parsed (I think), but that's fine with what I need.
而不是super的generic_visit,它导致了递归。这也极大地提升了性能。缺点是只解析模块全局范围内的语句(我认为),但这对我需要的很好。