2022年 11月 4日

python教程 —- 如何遍历文件夹

一、问题来源

遍历文件夹是python最常用的操作,比如训练神经网络需要的图片输入、对文件的处理等。近期想编写一个对图像加密所用的exe程序,需要用到加密选中的文件夹中所有的图片,这时我就开始思考:怎么可以使得遍历的速度较快?怎么使得占用的资源较少?

二、遍历方法

1. 递归

递归是我想到的最直接的遍历方法,类似深度搜索。使用python来写函数的递归肯定是比较慢的(当遍历的文件夹深度较深、数量较大时),如果是文件夹较少时可以使用该方法,因为确实很直接。
 

缺点也很明显,就是需要专门去区分文件夹和你所需要的文件。
另外速度比较慢,循环都是用python写的,相比c语言要慢的多。
当文件数量较大时,需要占用较多的内存。

  1. import os
  2. def mywalk(dir):
  3. for m in os.listdir(dir):
  4. if m[-4:] == '.bmp':
  5. file = os.path.join(dir, m)
  6. print('file: ', file)
  7. else:
  8. file = os.path.join(dir, m)
  9. mywalk(file)
  10. mywalk('./data/')

2. os.walk+迭代

os.walk是专门针对遍历文件夹中的文件的库,底层代码是C/C++写的,速度要快,示例为os.walk的用法。
 

  1. import os
  2. for root,dirs,files in os.walk(r"./data/"):
  3. '''
  4. root: 根目录
  5. dirs:根目录下的文件夹目录
  6. files:根目录下的文件目录
  7. '''
  8. for file in files:
  9. print('root: ', root)
  10. print('dirs: ', dirs)
  11. print('files: ', files)

结果示例:

  1. root: ./data/
  2. dirs: ['log_bmp']
  3. files: ['20190109_150108_0262_0.80.bmp']
  4. root: ./data/log_bmp
  5. dirs: ['20190108', '20190109']
  6. files: ['20190109_150108_0262_0.80.bmp']
  7. root: ./data/log_bmp\20190108
  8. dirs: []
  9. files: ['20190108_194653_0221_1.13.bmp', '20190108_194657_0262_0.79.bmp']
  10. root: ./data/log_bmp\20190108
  11. dirs: []
  12. files: ['20190108_194653_0221_1.13.bmp', '20190108_194657_0262_0.79.bmp']
  13. root: ./data/log_bmp\20190109
  14. dirs: []
  15. files: ['20190109_150108_0262_0.80.bmp']

以上我们解决了遍历速度的问题,还需要解决文件过大的问题。
参考:https://www.cnblogs.com/wj-1314/p/8490822.html 
确定了我们使用生成器的表达式:在for循环的基础上添加一个小括号。示例如下:

  1. import os
  2. path_collection = (os.path.join(root,fn) for root,dirs,files in os.walk('./data') for fn in files)
  3. for m in path_collection:
  4. print(m)

划重点:
生成器:一边循环一边计算,可以节省内存

 三、总结

1. 尽量使用python自带的库,因为底层是用C/C++写的,速度比较快
2. 尽量使用生成器代替列表,这样可以节省内存
3. 在神经网络的训练中,加载数据库就是使用了生成器的方法,边加载边计算
有兴趣可以看一下:https://blog.csdn.net/sinat_42239797/article/details/90641659