2016-10-20 5 views
0

Ich möchte alle Dateien in einem Verzeichnisbaum mit einer bestimmten Dateierweiterung finden. Einige Ordner sind jedoch sehr groß und daher möchte ich diesen Vorgang stoppen, wenn es zu lange dauert (etwa 1 Sekunde). Meine aktuellen Code sieht in etwa wie folgt aus:Erzwingen von os.walk zu stoppen, wenn zu lange dauern

import os 
import time 

start_time = time.time() 
file_ext = '.txt' 
path = 'C:/' 
file_list = [] 
for root, dirs, files in os.walk(path): 
    for file in files: 
     if file.endswith(file_ext): 
      relDir = os.path.relpath(root, path) 
      relFile = os.path.join(relDir, file) 
      file_list.append(relFile) 
     if time.time() - start_time> 1: 
      break 
    if time.time() - start_time> 1: 
     break 

Das Problem mit diesem Code ist, dass, wenn ich zu einem wirklich großen Unterordner bekommen, dieser Code nicht brechen, bis der Ordner vollständig durchlaufen wurde. Wenn dieser Ordner viele Dateien enthält, kann es viel länger dauern, als ich möchte. Kann ich irgendwie sicherstellen, dass der Code nicht viel länger als die zugewiesene Zeit läuft?

Edit: Beachten Sie, dass, obwohl es sicherlich hilfreich ist, Wege zu finden, um den Code zu beschleunigen (zum Beispiel mit os.scandir), diese Frage in erster Linie befasst sich mit einem laufenden Prozess zu töten.

+0

setzen Sie es in eine Funktion und verwenden Sie Return? –

+0

Leider ergibt das das gleiche Ergebnis. – matnor

+0

Ihre Einrückung ist wahrscheinlich falsch dann ... versuchen Sie, Ihre Frage in Ihren Editor einfügen und sehen, ob es funktioniert –

Antwort

0

Sie können den Schritt in einem Subprozess tun und das töten. Zu den Optionen gehören multiprocessing.Process, aber die Multiprocessing-Bibliotheken unter Windows müssen möglicherweise eine Menge Arbeit verrichten, die Sie nicht benötigen. Stattdessen können Sie den Walker-Code einfach in einen Python-Subprozess pipen und von dort aus gehen.

import os 
import sys 
import threading 
import subprocess as subp 

walker_script = """ 
import os 
import sys 
path = os.environ['TESTPATH'] 
file_ext = os.environ['TESTFILEEXT'] 

# let parent know we are going 
print('started') 

for root, dirs, files in os.walk(path): 
    for file in files: 
     if file.endswith(file_ext): 
      relDir = os.path.relpath(root, path) 
      relFile = os.path.join(relDir, file) 
      print(relFile) 
""" 

file_ext = '.txt' 
path = 'C:/' 

encoding = sys.getdefaultencoding() 

# subprocess reads directories... additional python flags seek to 
# speed python initialization. If a linuxy system, forking would 
# be a good option. 

env = {'TESTPATH':path, 'TESTFILEEXT':file_ext} 
env.update(os.environ) 
proc = subp.Popen([sys.executable, '-E', '-s', '-S', '-'], stdin=subp.PIPE, 
    stdout=subp.PIPE,  # , stderr=open(os.devnull, 'wb')) 
    env = env) 

# write walker script 
proc.stdin.write(walker_script.encode('utf-8')) 
proc.stdin.close() 

# wait for start marker 
next(proc.stdout) 

# timer kills directory traversal when bored 
threading.Timer(1, proc.kill).start() 

file_list = [line.decode(encoding).strip() for line in proc.stdout] 
print(file_list) 
+0

Die Verwendung des obigen Codes gibt mir den Fehler 'Fatal Python error: Fehler beim Initialisieren von Windows Random API (CryptoGen)'. Ich bin nicht sehr vertraut mit Subprozess, so bin ich nicht wirklich sicher, wie man den Fehler interpretiert. Danke für den Vorschlag, ich muss etwas tiefer in die Verwendung von Subprozessen einsteigen. – matnor

+0

@matnor - Ich war ein bisschen über aggressiv beim Beschneiden der Verarbeitungsumgebung des Kindes. Ich habe den Code aktualisiert, um die Umgebung des Elterns zu klonen. Wenn Sie immer noch ein Problem haben, können Sie die Flags "-E -s -S" entfernen, die nur dazu da sind, die Ladezeit von Python zu beschleunigen. – tdelaney

+0

Danke, der Code läuft jetzt. Leider wird das Skript nach einer Sekunde nicht beendet, sondern läuft weiter. – matnor

Verwandte Themen