【问题标题】:Getting error "Maximum recursion depth exceeded while calling a Python object"出现错误“调用 Python 对象时超出最大递归深度”
【发布时间】:2019-04-27 00:56:35
【问题描述】:

所以我刚刚收到一个错误,我有点不明白是什么原因。

Traceback (most recent call last):
  File "C:\Users\utils.py", line 657, in script
    logger.warn('Wopsiy! No word found!')
  File "C:\Users\utils.py", line 30, in warn
    sys.stdout.write("{}{} {}".format(self.__timestamp(), '[' + self.name + '] -', colored(text, "yellow")))
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 40, in write
    self.__convertor.write(text)
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 141, in write
    self.write_and_convert(text)
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 166, in write_and_convert
    self.write_plain_text(text, cursor, start)
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 174, in write_plain_text
    self.wrapped.write(text[start:end])
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 40, in write
    self.__convertor.write(text)
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 141, in write
    self.write_and_convert(text)
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 169, in write_and_convert
    self.write_plain_text(text, cursor, len(text))
  File "C:\Program Files\Python36\lib\site-packages\colorama\ansitowin32.py", line 174, in write_plain_text
    self.wrapped.write(text[start:end])

我可以看到它与我自己创建的记录器有一些类似的东西:

实用程序类

from datetime import datetime
from termcolor import cprint, colored
import sys

import colorama

class Logger:

    def __init__(self,name):
        colorama.init()
        self.name = name

    @staticmethod
    def __timestamp():
        timestamp = str(datetime.now().strftime("[%H:%M:%S.%f")[:-3]+"]")
        return timestamp

    def warn(self, text):
        sys.stdout.write("{}{} {}".format(self.__timestamp(), '[' + self.name + '] -', colored(text, "yellow")))
        sys.stdout.write("\n")
        sys.stdout.flush()

基本上我也做了一个简单的代码来说明我的代码是什么样的:

from utils import Logger
logger = Logger('Script')

def main():
    logger = Logger("product_info")
    word = ['Nope', 'There', 'Is', 'No', 'Word']
    while True:

        try:

            for _ in infinity():
                 if 'Hello' in word:
                     print('WORKS!!')

            else:
                logger.warn('Wopsiy! No word found!')
                time.sleep(1)

         except Exception as err:
              print(err)
              time.sleep(1)
              continue

所以问题是,过了一会儿它给了我maximum recursion depth exceeded while calling a Python object 的错误,但我只有在打印出except Exception as err: 时才会得到它,但是当我通过控制台查看时,它会给我顶部给出的输出.

现在的问题是,我实际上不知道它的原因是什么。

编辑

from datetime import datetime
from termcolor import cprint, colored
import sys

import colorama
colorama.init()
class Logger:

    def __init__(self,name):
        self.name = name

    @staticmethod
    def __timestamp():
        timestamp = str(datetime.now().strftime("[%H:%M:%S.%f")[:-3]+"]")
        return timestamp

    def warn(self, text):
        sys.stdout.write("{}{} {}".format(self.__timestamp(), '[' + self.name + '] -', colored(text, "yellow")))
        sys.stdout.write("\n")
        sys.stdout.flush()

【问题讨论】:

  • 看起来像这个问题的一个实例:github.com/tartley/colorama/issues/140
  • 如果我理解正确,当您多次调用 colorama.init() 时可能会出现此问题。尝试将此调用从 Logger 构造函数移到全局范围内。
  • @KT.你可能是对的,你有任何例子将 Logger 移出到全局会有帮助吗?
  • 把 colorama.init 放在 import colorama 之后。据我了解,这个 init 调用使用 colorama 过滤器包装全局流,当您再次重新包装它们(通过多次调用 colorama.init)时,情况会变得更糟。
  • 例如,“for i in range(1000): colorama.init()”这行代码让我的解释器崩溃了。

标签: python python-3.x error-handling runtime-error


【解决方案1】:

正如我从 cmets 中对问题的讨论中了解到的那样,您可以在执行脚本期间创建 Logger 类的多个实例。 Logger 的每次创建都会调用 colorama.init()。每次调用 colorama.init() 都会强制 Colorama 将 sys.stdoutsys.stderr 流替换为它们的 colorama 包装版本。

在越来越多地调用colorama.init 之后,您的流变成了许多(无用重复的)colorama 包装层的肥洋葱,并且对print 的单个调用必须逐层递归传递,直到它到达实际sys.stdout

当层数超过允许的最大堆栈深度时,您会遇到异常。 this open colorama issue中也提到了这种情况。

解决问题的最简单方法是将colorama.init() 移出Logger 构造函数,并在全局范围内使用类似的东西:

import colorama
colorama.init()

【讨论】:

  • 这似乎是真正的问题,我会尝试尝试并给它几个小时!如果没有问题,我会回来的!
  • 似乎有效!试了2天,没有一个错误!