Python内存不足错误,多线程子目录递归

时间:2015-05-18 16:31:19

标签: python multithreading recursion

我第一次使用递归进行实验,并在扫描大目录时遇到问题。以下代码采用了一个glob模式列表(例如,[' / opt / data / large_dir_1 *',' / opt / data' large_dir_2']),扩展了glob模式,将生成的文件/目录列表传递给线程,总计找到的目录数,找到的文件数以及找到的文件的总字节大小。子目录很大(其中有几个有数十万个目录,数百万个文件),但我很惊讶我生成的一些线程正在抛出" MemoryError"异常。

我的猜测是问题正在发生,因为' dirList'和' fileList'变量占用了太多的内存。我的备份计划是让递归函数简单地将数据写入日志文件而不是将其返回,但我试图避免使用全局'变量尽可能多。有没有人对更好的方法有任何想法?我在这里做些蠢事吗?感谢您提供的任何帮助。

def Scan(masterFileList, baseDir='/'):
    dirList = []
    fileList = []
    byteCount = 0
    for fileOrDir in masterFileList:
        fullName = os.path.join(baseDir,fileOrDir)
        if os.path.isdir(fullName):
            dirList.append(fullName)
            # recursion: call Scan():
            dirs, files, bytes = Scan(os.listdir(fullName),fullName)
            dirList.extend(dirs)
            fileList.extend(files)
            byteCount += bytes
        elif os.path.isfile(fullName):
            fileList.append(fullName)
            byteCount += os.path.getsize(fullName)
    return dirList, fileList, byteCount


dirList = []
fileList = []
byteCount = 0
errorList = []

def doScan(dataQueue):
    print('Thread starting')

    while not dataQueue.empty():
        globPattern = dataQueue.get()
        globbed = glob.glob(globPattern)
        if globbed:
            dirs, files, bytes = Scan(globbed)
            # if we have a lock:
            with safePrint:
                dirList.extend(dirs)
                write_to(dirLog, 'a', dirs) 
                fileList.extend(files)
                write_to(fileLog, 'a', files)       
                byteCount += bytes
                # convert to string for writing:
                write_to(byteLog, 'w', str(byteCount))
        else:
            # if we have a lock:
            with safePrint:
                errorList.append(globPattern)
                write_to(errorLog, 'a', globPattern)                

    print('Thread exiting')

numthreads = 0
for globPattern in globList:
    dataQueue.put(globPattern)
    numthreads += 1

# initialize threads:
threads = []
for i in range(numthreads):
        thread = threading.Thread(target=doScan, args=(dataQueue, ))
        threads.append(thread)
        thread.start()

# wait until threads are done:
for thread in threads: thread.join()

1 个答案:

答案 0 :(得分:1)

这听起来像是os.walk的完美用例,它允许您使用简单的for循环递归遍历文件系统。 https://docs.python.org/3/library/os.html#os.walk上的官方文档包含一个与您的用例非常相似的示例。

如果要进行多线程处理,可以启动使用queue.Queue中可以从此for循环填充的项目的工作线程。