【问题标题】:Python: maximum recursion depthPython:最大递归深度
【发布时间】:2011-08-29 21:32:28
【问题描述】:

下面给出了一个用于返回其参数大小总和的函数,该参数可以是单个文件/目录或文件/目录列表。该代码给出了错误消息RuntimeError: maximum recursion depth exceeded while calling a Python object 但是我尝试对此进行测试。

如何解决这个问题?

谢谢

放心

#!/usr/bin/python3.1
import os

def fileSizes(f):
    if hasattr(f,'__iter__'):
        return sum(filter(fileSizes,f))
    if os.path.isfile(f):
        return os.path.getsize(f)
    elif os.path.isdir(f):
        total_size = os.path.getsize(f)
        for item in os.listdir(f):
            total_size += fileSizes(os.path.join(f, item))
        return total_size

【问题讨论】:

  • listdir 是否包含当前目录?你循环的迭代器是什么?
  • os.listdir() 不包括当前目录或父目录。

标签: python recursion


【解决方案1】:

使用内置的os.walk(Documentation) 方法,而不是编写自己的临时目录横向方法。

事实上,文档中的示例(上面的链接)计算了非目录文件的总大小。

【讨论】:

  • 但是os.walk() 又调用listdir() 对吗?我在上面的代码中使用listdir()..那么它仍然可以称为adhoc吗?
  • os.walk 调用os.listdir(),它的行为方式与您的代码相同,但它是迭代的,并且允许跟随/忽略符号链接。你真的应该看看文档,那里的一切都很清楚。
【解决方案2】:

上次我检查时,默认的最大递归深度是 1000。你有几个选择:

  1. 使用Stackless Python,它不施加递归限制(允许无限递归)。
  2. 以迭代方式而不是递归方式重写您的函数,这样一开始就不会溢出堆栈。
  3. 使用sys.setrecursionlimit 设置最大递归限制。请注意,如果滥用,这可能会导致分段错误。

【讨论】:

  • -1:在程序中设置 sys.setrecursionlimit 是不安全的,可能会导致段错误。唯一正确的情况是您编写一次性使用脚本时。 ://
  • @Devin 并不意味着我不能告诉他这是一个选择。
  • @Devin 我们是否应该永远不要使用 C,因为您编写的每个 C 程序都“可能存在段错误”?如果让您感觉好些,我会切换顺序并添加警告。
【解决方案3】:

问题出在一行:

if hasattr(f,'__iter__'):
    return sum(filter(fileSizes,f))

由于f是一个路径,它是一个字符串,它有__iter__的属性,所以你无限循环到那里。

【讨论】:

  • 哦,那我该如何测试对字符串无效的列表呢?好的,我相信我可以使用 isinstance()....
  • 这是否解决了您的问题?关于你的第二个问题,你可以试试type(f) != str and hasattr(f,'__iter__') ...
  • @rm 我使用了isinstance。递归问题消失了,但 sum(filter(...)) 给了我一些其他类型的错误......
  • 太好了,我修复了你的原始代码。尝试自己解决其余问题或在此处提出另一个问题。
  • 好的,这是一个不同的问题,(不是 cmets 的用途),但我认为您的意思是在代码中使用 map,而不是 filter。如果您有任何其他问题,问其他问题,不要继续在 cmets 中添加它们。
【解决方案4】:

有很多技巧可以避免深度递归的问题,但我怀疑这不是你的核心问题。 (也许是如果你有非常深的目录结构..所以先在浅目录上测试)。

我猜您在目录树中发现了由链接引起的循环结构。 IE。指向父目录的符号链接目录。 (这种结构并不少见)。

您可以通过在关注目录之前检查目录是否为符号链接来避免无限循环。

另一种可能性是你得到“。”或“..”列表中的某处。这些也会产生无限循环。我认为这里不会发生这种情况,但值得考虑。 os.listdir 似乎没有返回它们。

【讨论】:

  • @Anderson,我尝试在浅目录上运行,但看起来,无论参数如何,代码都会给出相同的错误消息。所以我现在无法测试它......
  • 在我的目录中“按原样”运行代码会产生结果 - 特别是我在几个目录中尝试了 fileSize(".")。但是结果看起来不对..(例如我在空目录中运行时得到 68)。
猜你喜欢
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 2020-07-13
  • 2021-02-07
  • 2016-07-09
  • 2017-03-18
  • 2015-04-15
相关资源
最近更新 更多