1

我的目标是从dir. 因此,我尝试编写一个 Python 脚本来执行此操作。第一个场景是这样

#!/usr/bin/python

import os,sys
dirname = os.getcwd() if len(sys.argv) == 1 else sys.argv[1]
deleteConfirm = raw_input('Delete all files from dir ' + str(dirname) + ' (y/n)? ')
if(deleteConfirm not in ['y','Y']):
    os._exit(0)

counter = 0
flist = os.listdir(dirname)
for file in flist:
    os.remove(os.path.join(dirname, file))
    counter+=1
    if(0==counter%1000):
        sys.stdout.write('\rDeleted %d files' % counter)
        sys.stdout.flush()

print '\nDeleted %d files' % counter

这段代码有效,但我发现它每 10-15 秒停止一次,并且在几分钟左右不起作用。例如,前几秒钟的场景快速输出已删除文件的数量 - 它删除 28 000 个文件只需 3-5 秒,但随后其输出停止在“已删除 28000 个文件”并等待很长时间 - 分钟左右。然后再次输出快速更新,并在几秒钟内再次删除数千个文件。但话又说回来,它停下来等待着什么。我认为这是由于锁定的文件,所以我尝试编写新的场景,使用 python3 和多处理模块,在几个进程中删除文件。我认为这可能会有所帮助,因为即使一个进程等待某个文件解锁,其他进程也会完成他们的工作。

是新脚本:

#!/usr/bin/python3

import os, sys, time
from multiprocessing import Pool
dirname = os.getcwd() if len(sys.argv) == 1 else sys.argv[1]
procNum = 5 if len(sys.argv) < 3 else sys.argv[2]
deleteConfirm = input('Delete all files from dir ' + str(dirname) + ' (y/n)? ')
if(deleteConfirm not in ['y','Y']):
    sys.exit()

def main():
    flist = os.listdir(dirname) 
    count = len(flist)
    if count < 100000:
        counter = 0
        for file in flist:
                os.remove(os.path.join(dirname, file))
                counter+=1
                if(0==counter%1000):
                    sys.stdout.write('\rDeleted %d files' % counter)
                    sys.stdout.flush()
            print('\rDeleted %d files' % counter)
            sys.exit(0)
        else:
            workers = Pool(processes=procNum)       
            result = workers.imap_unordered(delfile,flist)
        workers.close()
        while True:
                    time.sleep(5)
                    completed = result._index
                    if completed == count:
                        print('')
                        break
                    sys.stdout.write('\rRemoved %d files' % result._index)
            workers.join()

def delfile(fname):
    os.remove(os.path.join(dirname,fname))

我尝试了这个新脚本,但它每隔几秒钟就停止一次,就像之前的场景一样。我想不通,为什么会这样。有任何想法吗?

4

1 回答 1

5

详细信息在 Linux 文档中,假设您使用的是 Linux(其他操作系统可能不同):例如参见https://www.kernel.org/doc/Documentation/sysctl/vm.txt

Linux 通过创建“脏页”来处理对磁盘的写入,脏页是等待物理副本到磁盘的内存部分。物理副本稍后出现。这就是为什么os.remove()通常非常快:它只会在内存中创建或修改一个页面,并将物理副本留给以后使用。(如果很快我们再做一次os.remove()需要更改同一内存页的操作,那么我们就赢了:无需多次将该页写入磁盘。)

通常,一个名为“pdflush”的守护进程会定期唤醒以执行此写入磁盘。但是,如果一个进程确实生成了很多脏页,那么内核将在某一时刻停止它(在随机的一次os.remove()调用期间)并强制现在对部分待处理页面进行写入磁盘。只有当脏页再次低于合理阈值时,它才允许程序继续运行。很可能,“pdflush”将立即继续编写其余部分。显然,如果你的程序继续产生脏页,它会再次达到上限并再次暂停。

这就是导致您的流程暂停的原因。这是内核工作方式的副作用。你可以忽略它:物理上,磁盘一直都很忙。

于 2013-05-23T20:57:41.467 回答