写一个好的循环体来处理数据
Lyndon Wong

起因

在我们日常处理数据的时候,最常见的一种便是遍历某个目录(或某个多级目录),对该目录下面的每个文件进行一定的处理。比方说,通过raw数据处理后得到精修的数据、检测数据集中的图片中的目标并且将检测结果按需保存。这似乎是一个很基础的任务,但是其实我们可以将其完成地更好。

目录格式

为了简单起见,我们假设现在我们要处理数据的目录格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
dataset/
-folder1/
-img1.jpg
-img2.jpg
...
-folder2/
-img1.jpg
-img2.jpg
...
-folder3/
-img1.jpg
-img2.jpg
...

我们需要读取每张图片,并且将其转换为png格式保存。转换为png格式的函数为jpg2png,接下来笔者推荐了一种循环体。

一个成熟的循环体

一个好的遍历循环最好包括以下三部分:

  • 进度打屏显示
  • 异常处理
  • 错误信息记录

用python代码格式写一下就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
log_file #错误信息路径
dataset_path #数据集路径
save_path # 处理完的数据集保存路径

folder_list = os.listdir(dataset_path) #子文件夹名称列表

for i in range(len(folder_list)):#遍历子文件夹
folder_path = os.path.join(dataset_path,folder_list[i])#子文件夹路径
img_list = os.listdir(folder_path)#图片名称列表
for j in range(len(img_list)):
print('folders: %d/%d, imgs:%d,%d'%(i,len(folder_list),j,len(img_list))) #打印实时进度
img_path = os.path.join(folder_path,img_list[j])
try: #进行处理
img = os.open(img_path)
img_out = jpg2png(img)
img_out_path = os.path.join(save_path,folder_list[i],img_list[j].split('.')[0],'png')
os.save(img_out,img_out_path)
except: #异常处理,将错误信息保存到log文件
with open("log.txt", "a") as logfile:
print("Got an exception while handling {!r} in the loop:".format(x)
traceback.print_exc(file=logfile)
logfile.close()

(1)进度打屏显示:为了让人实时了解程序运行情况,以及估计运行时间(python可用tqdm等库)

(2)异常处理:防止程序运行到一半发生错误,导致又要重新修改后遍历,这对于长的循环体很有必要!

(3)错误信息记录:方便我们后面逐个排查错误的文件的地址和原因

 评论