正如标题中所说,有没有更好的方法可以在python中删除多个文件?目前,我是通过对每个文件进行循环删除。
import os
files = ["test_file.txt", "test_failed.txt"]
for file in files:
if os.path.exists(file):
os.remove(file)
让我们把这个问题看清楚。
我们从拆解 for
-循环进入字节码,使用 dis
模块。
In [23]: dis.dis('for f in files: os.remove(f)')
1 0 SETUP_LOOP 22 (to 24)
2 LOAD_NAME 0 (files)
4 GET_ITER
>> 6 FOR_ITER 14 (to 22)
8 STORE_NAME 1 (f)
10 LOAD_NAME 2 (os)
12 LOAD_METHOD 3 (remove)
14 LOAD_NAME 1 (f)
16 CALL_METHOD 1
18 POP_TOP
20 JUMP_ABSOLUTE 6
>> 22 POP_BLOCK
>> 24 LOAD_CONST 0 (None)
26 RETURN_VALUE
这里唯一真正的 "困难"(而且是小困难)是重复查找名称 os.remove
. 所以,我们先为它创建一个本地别名来摆脱它。
In [24]: rm = os.remove
Out[24]: <function posix.remove(path, *, dir_fd=None)>
In [25]: dis.dis('for f in files: rm(f)')
1 0 SETUP_LOOP 20 (to 22)
2 LOAD_NAME 0 (files)
4 GET_ITER
>> 6 FOR_ITER 12 (to 20)
8 STORE_NAME 1 (f)
10 LOAD_NAME 2 (rm)
12 LOAD_NAME 1 (f)
14 CALL_FUNCTION 1
16 POP_TOP
18 JUMP_ABSOLUTE 6
>> 20 POP_BLOCK
>> 22 LOAD_CONST 0 (None)
24 RETURN_VALUE
这样可以节省 单字节码指令 (LOAD_METHOD
)每个文件。
一般来说,列表理解 可以 快于 for
-循环。但当我尝试使用10个空的但现有的文件的列表时。
In [15]: %timeit -n1 -r1 for f in files: os.remove(f)
71.3 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
与使用本地别名的列表理解相比。
In [32]: %timeit -n1 -r1 [rm(f) for f in files]
71 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
有 实际上 没有区别。
在最近的UNIX系统上测量 (FreeBSD 12, UFS文件系统在硬盘上,使用 %timeit
在IPython中)。)
os.path.exists()
在一个循环中,每个文件大约需要2 µs。os.remove()
在循环中,每个文件大约需要7-10 µs。在循环中使用 os.stat
直接而不是通过 exists
并没有太大的区别。而 os.remove
使用 remove(3)
C库的调用。所以它的大部分时间都花在了文件系统操作上,而这些操作本质上都是 很慢 与现代CPU相比。
所以除了用C语言写这个东西,直接用系统调用(不是C库函数),可能也没什么好处。
你做的事情并没有什么特别低效的地方。
不过如果你想删除整个目录,可以用rmtree。
import shutil
shutil.rmtree('/my-dir/')
这个速度的方法不多。文件的最终删除将不得不使用以下方法来完成(至少在Linux上,我猜测你的操作系统是基于文件名的)。unlink(2)
系统调用,一次只能删除一个文件。我猜想文件系统会做一些诡计来给你提供一种并行性,所以可能会通过使用多个进程来获得一些速度的提升。这里有一些其他的建议。
if os.path.exists
. 这将运行一个 stat(2)
来检查文件是否存在,而且每次循环的迭代都会增加固定的时间。最好是直接去删除它,如果文件不存在,就抓住异常,忽略它,然后继续前进(原谅而不是权限)。