2010-11-04 40 views
11

我有一個目錄中有90K文件。這是如此巨大數量的文件,像ls這樣的bash函數失敗。所以當然,從我的Python(Mac Python,版本2.5)腳本os.listdir();它失敗OSError: [Errno 12] Cannot allocate memory: '.'解決OSError與os.listdir

人們會說:「不要把這麼多文件放在一個目錄中!你瘋了嗎?」 - 但我喜歡假裝我生活在未來,一個輝煌燦爛的地方,在那裏我擁有十億字節的內存,並且不需要過多擔心我的文件到底在哪裏,只要有我的旋轉盤片上留有鏽跡。

那麼,對於os.listdir()這個問題,有沒有很好的解決方法?我已經考慮過僅僅支持find,但這有點嚴重,不幸的是find是遞歸的,在Mac OS X 10.6上沒有支持maxdepth選項。

這裏是通過脫殼而出找的樣子,大致os.listdir:

def ls(directory): 
    import os 
    files = os.popen4('find %s' % directory)[1].read().rstrip().split('\n') 
    files.remove(directory) 
    return files # probably want to remove dir prefix from everything in here too 

更新:os.listdir()成功在Python 2.6。

+2

你得到的錯誤是什麼?我經常使用'os.listdir'來獲取包含50-100k文件的目錄列表。 'os.listdir'也是最快的選擇,因爲它不會對目錄中的每個文件進行「統計」。 – Seth 2010-11-04 16:32:45

+0

@Seth,我得到OSError:[Errno 12]無法分配內存:'。' – 2010-11-04 16:34:21

+0

這個目錄中大概有多少個文件? – 2010-11-04 16:43:23

回答

2
def ls(directory): 
    """full-featured solution, via wrapping find""" 
    import os 
    files = os.popen4('find %s' % directory)[1].read().rstrip().split('\n') 
    files.remove(directory) 
    n = len(directory) 
    if directory[-1] != os.path.sep: 
     n += 1 
    files = [f[n:] for f in files] # remove dir prefix 
    return [f for f in files if os.path.sep not in f] # remove files in sub-directories 
+1

什麼是downvotes,你們都? – 2010-11-04 17:39:28

+0

是的,它會工作,但不會幫助解決90k文件的性能問題。 – 2010-11-04 22:37:35

+0

我只是在尋找一些可以工作的東西 - 不關心性能,一個不起作用的解決方案isn 't解決方案 – 2010-11-05 14:13:01

4

您可以嘗試深入一層,直接使用ctypes調用opendir()和readdir()。

+0

絕望,但是如果'listdir'和'ls'失敗,這是我能想到的唯一的事情 – bobince 2010-11-04 16:54:29

+0

這是誘人的,但問題是'readdir'將數據作爲'struct direct'返回,並且th的佈局at是平臺特定的。我認爲唯一的*可靠*的方式來實現這是一個本地模塊。 – 2010-11-04 16:55:04

7

你正在Python中遇到一個歷史工件:os.listdir應該返回一個迭代器,而不是一個數組。我認爲這個函數早於迭代器 - 奇怪的是沒有添加os.xlistdir

這不僅僅是巨大目錄上的內存使用情況。即使在只有幾千個文件的目錄中,您也必須等待整個目錄掃描完成,並且您必須閱讀整個目錄,即使第一個條目是您正在尋找的目錄。

這是一個非常明顯的缺乏在Python:似乎有沒有opendir/readdir/fdopendir的API綁定到低級別的,所以它看起來像它甚至不是可以自己實現,而無需編寫本機模塊。這是標準庫中這樣一個巨大的漏洞,我懷疑自己和懷疑我只是沒有看到它 - 有低級open,stat等綁定,這是在同一類別。

+0

總是很高興看到神祕downvotes。我想這是「敢於批評Python」的懲罰。 – 2010-11-04 16:57:57

+1

'ImportError:No module named criticize' – Seth 2010-11-04 17:20:38

+0

這意味着'ImportError:No module named improvement'。 – 2010-11-04 17:34:39

2

在列出大目錄時,我在10.6上的Apple Python 2.5.5上得到了相同的IOError。它在Python2.6中工作得很好。

Python 2.5.5 (r255:77872, Sep 21 2010, 09:52:31) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> x = os.listdir('.') 
OSError: [Errno 12] Cannot allocate memory: '.' 

這似乎是Python2.5中的一個錯誤。參見「os.listdir randomly fails on occasions when it shouldn't」和「Sloppy error checking in listdir() for Posix」。