Twisted 有时抛出(似乎不完整的)“超过最大递归深度”RuntimeError

2 投票
3 回答
1334 浏览
提问于 2025-04-15 12:47

因为Twisted的getPage函数不能让我访问请求头,所以我不得不自己写一个getPageWithHeaders函数。

def getPageWithHeaders(contextFactory=None, *args, **kwargs):
    try:
        return _makeGetterFactory(url, HTTPClientFactory,
                                  contextFactory=contextFactory,
                                  *args, **kwargs)
    except:
        traceback.print_exc()

这个函数和普通的getPage函数完全一样,只是我加了一个try/except块,并且返回的是工厂对象,而不是返回工厂的deferred。

奇怪的是,我有时候会在这里遇到“最大递归深度超出”的错误。这种情况在700次中大约会发生几次,通常每次都是在不同的网站上。有人能帮我解释一下吗?我不太明白为什么会这样,而且Twisted的代码库很大,我都不知道该从哪里入手。

编辑:这是我得到的错误追踪信息,看起来奇怪得不完整:

Traceback (most recent call last):
  File "C:\keep-alive\utility\background.py", line 70, in getPageWithHeaders
    factory = _makeGetterFactory(url, HTTPClientFactory, timeout=60 , contextFactory=context, *args, **kwargs)
  File "c:\Python26\lib\site-packages\twisted\web\client.py", line 449, in _makeGetterFactory
    factory = factoryFactory(url, *args, **kwargs)
  File "c:\Python26\lib\site-packages\twisted\web\client.py", line 248, in __init__
    self.headers = InsensitiveDict(headers)
RuntimeError: maximum recursion depth exceeded

这是整个错误追踪信息,明显没有长到会超出我们的最大递归深度。我还需要做些什么才能得到完整的堆栈信息吗?我以前从来没有遇到过这个问题;通常当我做类似的事情时

def f(): return f()
try: f()
except: traceback.print_exc()

我会得到那种“最大递归深度超出”的堆栈信息,里面会有很多对f()的引用。

3 个回答

-1

这个网址打开器可能正在经历一连串不断的301或302重定向。

1

你应该看看你收到的错误信息和异常提示,这会告诉你哪个函数在不断地重复调用,也就是在_makeGetterFactory下面的那些函数。很可能是你自己写的getPageWithHeaders函数参与了这个重复调用,因为它没有正确地返回一个“延迟”对象,而是试图返回一个还没准备好的工厂。如果你真的改回去,返回那个“延迟”对象,会发生什么呢?

2

你看到的这个错误追踪信息有点让人困惑。你可以试试用 traceback.print_stack,而不是 traceback.print_exc,这样可以查看到出问题的代码上面所有的调用记录,而不仅仅是异常被捕获的地方。

我不能确定,因为我没有看到更多的错误追踪信息,但你可能遇到了一个问题,就是如果你把太多的 Deferred(延迟对象)串在一起,就会引发递归限制的异常。你可以在这里查看相关信息:这个链接

如果你开启 Deferred 的调试模式(用 from twisted.internet.defer import setDebugging; setDebugging(True)),在某些情况下你可能会得到更有用的错误追踪信息,但请注意,这样可能会让你的服务器变得比较慢。

撰写回答