2011-08-29 200 views
2

下面給出了一個用於返回其參數大小總和的函數,該函數可以是單個文件/目錄或文件/目錄列表。該代碼給出了錯誤消息RuntimeError: maximum recursion depth exceeded while calling a Python object但是我嘗試測試這個。Python:最大遞歸深度

如何解決這個問題?

感謝

蘇雷什

#!/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 
+0

listdir包含當前目錄嗎?你正在循環的迭代是什麼? –

+0

'os.listdir()'不包含當前或父目錄。 – suresh

回答

1

的問題是在該行:

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

由於f是一個路徑,它是一個字符串,它具有屬性__iter__,所以你有循環無限。

+0

哦,那我該如何測試對字符串無效的列表呢?好的,我可以使用isinstance()我相信.... – suresh

+0

是否解決了您的問題?關於你的第二個問題,你可以嘗試'type(f)!= str和hasattr(f,'__ iter __')'...... –

+0

@rm我使用了'isinstance'。遞歸問題消失了,但是sum(filter(...))'給了我一些其他類型的錯誤... – suresh

2

我最後一次檢查,默認最大遞歸深度爲1000您有幾種選擇:

  1. 使用Stackless Python它並沒有規定遞歸限制(允許無限遞歸)。
  2. 以迭代風格而不是遞歸重寫你的函數,所以你不會首先溢出堆棧。
  3. 使用sys.setrecursionlimit設置最大遞歸限制。注意,如果濫用,這可能會導致分段錯誤。
+0

-1:在程序中設置sys.setrecursionlimit是不安全的,可能會導致段錯誤。唯一一次這是正確的是當你正在編寫一次性使用腳本。 :/ –

+2

@Devin並不意味着我不能告訴他這是一個選擇。 –

+0

@Devin我們是否應該永遠不要使用C語言,因爲您編寫的每個C程序都是「可能存在缺陷?」如果讓你感覺更好,我會切換順序並添加警告。 –

1

有很多技巧可以避免深度遞歸問題,但我懷疑這不是您的核心問題。 (也許這是如果你有很深的目錄結構..所以先測試一個淺層目錄)。

我猜你在鏈接引起的目錄樹中找到了一個循環結構。 也就是說指向父目錄的符號鏈接目錄。 (這種結構並不罕見)。

您可以通過檢查目錄是否爲符號鏈接來避免無限循環。

另一個可能性是你得到「。」。或「..」在您的列表中的某處。這些也會產生無限循環。我沒有看到發生在這裏,但它值得思考。 os.listdir似乎不會返回它們。

+0

@Anderson,我試着在一個淺層目錄上運行,但是看起來像,不管參數如何,代碼都會給出相同的錯誤信息。所以我現在不能測試它... – suresh

+0

在我的目錄中按原樣運行代碼會生成結果 - 特別是我在幾個目錄中嘗試了'fileSize(「。」)''。但結果看起來不正確(例如,我在空目錄中運行時得到68)。 –

8

而不是編寫自己的adhoc目錄 - 橫向方法,請使用內置的os.walk(Documentation)方法。

實際上,文檔中的示例(上面的鏈接)計算了非目錄文件的總大小。

+0

但是'os.walk()'依次調用'listdir()'對嗎?我在上面的代碼中使用'listdir()'...所以它仍然可以被稱爲adhoc? – suresh

+0

'os.walk'調用'os.listdir()',它的行爲與你的代碼一樣,但是迭代地,也允許跟隨/忽略符號鏈接。你應該真的看看文檔,一切都很清楚。 – Can