如果花费太长时间,迫使os.walk停止

时间:2016-10-20 20:54:50

标签: python

我想在目录树中找到具有给定文件扩展名的所有文件。但是,有些文件夹非常大,因此如果花费太长时间(例如1秒),我想停止此过程。我当前的代码看起来像这样:

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

这段代码的问题在于,当我到达一个非常大的子文件夹时,在完全遍历该文件夹之前,此代码不会中断。如果该文件夹包含许多文件,则可能需要比我想要的更长的时间。有什么办法可以确保代码的运行时间不超过规定的时间吗?

编辑:请注意,虽然找到加速代码的方法肯定有帮助(例如使用os.scandir),但这个问题主要涉及如何终止正在运行的进程。

1 个答案:

答案 0 :(得分:0)

你可以在子进程中执行并杀死它。选项包括multiprocessing.Process,但Windows上的多处理库可能需要做大量您不需要的工作。相反,你可以将walker代码传递到python子进程中并从那里开始。

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)