簡體   English   中英

使用os.listdir解決OSError問題

[英]Workaround OSError with os.listdir

我有一個包含90K文件的目錄。 這是一個非常大量的文件,像ls這樣的bash函數會失敗。 當然,我的python(Mac Python,2.5版)腳本中的os.listdir()也是如此; 它因OSError: [Errno 12] Cannot allocate memory: '.'失敗OSError: [Errno 12] Cannot allocate memory: '.'

人們會說“不要把那么多文件放在一個目錄里!你瘋了嗎?” - 但我喜歡假裝我生活在未來,一個輝煌,發光的地方,我可以隨意使用千兆字節的內存,而且不需要太擔心我的文件到底在哪里,只要有我的旋轉盤片上留下了銹跡。

那么,這個os.listdir()問題有一個很好的解決方法嗎? 我認為只是在find ,但這有點嚴重,不幸的是find是遞歸的,在Mac OS X 10.6上沒有受支持的maxdepth選項。

這是os.listdir通過shell來查找的內容,粗略地說:

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中成功。

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

這比在巨大的目錄上使用內存更有效。 即使在只有幾千個文件的目錄上,您也必須等待整個目錄掃描完成,並且您必須讀取整個目錄,即使第一個條目是您正在查找的條目。

這是Python中一個非常明顯的缺點:似乎沒有綁定到低級opendir / readdir / fdopendir API,所以看起來甚至不能在不編寫本機模塊的情況下自己實現它。 這是標准庫中如此龐大,空洞的漏洞之一,我懷疑自己並懷疑我只是沒有看到它 - 有低級別的openstat等綁定,這是在同一類別。

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

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

列出一個大目錄時,我在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在不應該的情況下隨機失敗 ”和“ Posix的listdir()中的Sloppy錯誤檢查 ”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM