【发布时间】:2015-07-08 05:16:09
【问题描述】:
我的目标是从dir 中删除 1000 万个临时文件。因此,我尝试编写一个 Python 脚本来执行此操作。第一个场景看起来像that:
#!/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 和多处理模块,在几个进程中删除文件。我认为这可能会有所帮助,因为即使一个进程等待某个文件解锁,其他进程也会完成他们的工作。
Here 是新脚本:
#!/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))
我尝试了这个新脚本,但它每隔几秒就会停止一次,就像之前的场景一样。我想不通,为什么会这样。有什么想法吗?
【问题讨论】:
-
如果您的目录中确实有 1000 万个文件,那么您的文件系统可能会出现问题。您可能遇到了文件系统本身的一些瓶颈。
-
很少有操作系统是围绕“删除 1000 万个文件”作为常见用例而设计的。为什么有这么多文件?所有这些文件都在一个目录中吗?
-
同意@mgilson 的观点,问题可能出在 Linux 上,而不是 Python。我不知道
os.remove的内部工作原理是如何工作的,但它可能与击中外壳扩展块有关。尝试将此命令传递给 shell 而不是os.remove- 看看这是否有助于find . -exec /bin/rm {} \;(这应该消除任何 shell 扩展问题) -
@Andenthal 不太可能。
os.remove()比 shell 低层,所以使用 shell 可能会增加复杂性而不是删除。
标签: python linux performance filesystems delete-file