Durchsuchen von Verzeichnisbäumen (os.walk Alternative)
Verfasst: Samstag 9. Juli 2011, 15:25
Moin moin,
ich mache mittlerweile viele Datei-Sortier-, Aufräum- und Archivier-Arbeiten mit kleinen Python-Progrämmchen.
Dabei braucht man immer wieder Listen der Dateien und zughörige Metadaten. Mit os.walk und darauffolgendem os.stat kann das recht zeitaufwändig werden, wenn man mehrere Verzeichnisse mit vielen Dateien abgrasen muß.
Hier ist mal der erste Versuch das ein wenig zu beschleunigen:
Da ich Python-Newbie bin, wollte ich dieses Routinchen mal zum "Korrekturlesen" hier posten.
Ich stamme aus der Computer-Steinzeit und bin mit Fortran-77 und Pascal / Modula2 aufgewachsen. Die ersten CP/M-Rechner habe ich noch selbst gelötet.
Leider hab' ich in den letzten zwei Jahrzehnten nicht viel dazugelernt - ich bitte daher allfällige "un-Pythonische" Konstrukte zu entschuldigen und ggf, zu korrigieren.
mfg, Tom
ich mache mittlerweile viele Datei-Sortier-, Aufräum- und Archivier-Arbeiten mit kleinen Python-Progrämmchen.
Dabei braucht man immer wieder Listen der Dateien und zughörige Metadaten. Mit os.walk und darauffolgendem os.stat kann das recht zeitaufwändig werden, wenn man mehrere Verzeichnisse mit vielen Dateien abgrasen muß.
Hier ist mal der erste Versuch das ein wenig zu beschleunigen:
Code: Alles auswählen
# -*- coding: utf-8 -*-
import os, stat, Queue, threading
def get_direntries(pathlist):
'''scan [pathlist] and return all file-entries as a queue of tuples'''
class PushUrls(threading.Thread):
'''non-recursive walker'''
def __init__(self, pathque, tuplque):
threading.Thread.__init__(self)
self.pathque = pathque
self.tuplque = tuplque
def run(self):
while True:
pathstr = self.pathque.get() # pop path from fifo
try:
dirlist = os.listdir(pathstr)
except os.error:
dirlist = []
for direntry in dirlist:
urlstr = os.path.join(pathstr, direntry)
try:
stdict = os.stat(urlstr)
if not stat.S_ISLNK(stdict.st_mode): # don't follow links
if stat.S_ISDIR(stdict.st_mode): # if entry = subdir
self.pathque.put(urlstr) # push subdir
else:
self.tuplque.put((urlstr, stdict))
except os.error:
self.tuplque.put((urlstr, None)) # onerror: stat = None
self.pathque.task_done()
def max_threads(jobs):
try:
from multiprocessing import cpu_count
cores = cpu_count()
except ImportError:
cores = 2 # default: assume dual-core
return min([jobs * 2, cores * 2])
pathque, tuplque = Queue.Queue(), Queue.Queue()
for threadcount in range(max_threads(len(pathlist))):
scanins = PushUrls(pathque, tuplque)
scanins.setDaemon(True)
scanins.start() # start scanner-thread(s)
for path in pathlist:
pathque.put(path) # push path(s)
pathque.join() # block until fifo == empty
return tuplque # queue of (urlstring, os.stat)-tuples
#sample-call
print get_direntries(['C:\\', 'D:\\']).qsize()
Ich stamme aus der Computer-Steinzeit und bin mit Fortran-77 und Pascal / Modula2 aufgewachsen. Die ersten CP/M-Rechner habe ich noch selbst gelötet.
Leider hab' ich in den letzten zwei Jahrzehnten nicht viel dazugelernt - ich bitte daher allfällige "un-Pythonische" Konstrukte zu entschuldigen und ggf, zu korrigieren.
mfg, Tom