什么是异常?
异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。
常见的异常有:
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
其中,我们经常能遇到的ERROR有:KeyboardInterrupt、Exception、AssertionError、AttributeError、EOFError、IOError、ImportError、MemoryError、RuntimeError、SyntaxError、TypeError、ValueError、UnicodeError等
异常处理
捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
语法:
以下为简单的try....except...else的语法:
try:
<语句> #运行一行可能会出现错误的代码
except <名字>:
<语句> #如果在try部份引发了'name'异常,执行的语句
except <名字>,<数据>:
<语句> #如果引发了'name'异常,获得附加的数据
else:
<语句> #如果没有异常发生
最近在公司处理数据的时候,才了解到异常处理的方便所在~~
背景:
同事A和同事B都做了数据标注,并最后交予我整合数据,但是由于沟通上的问题和同事A和B的粗心,在图片统一命名的时候发生了一些不易发觉的错误,包含小错误的图片大概有十几二十张,这些图片很难发觉,因为图片总量有好几千张。
先介绍一些正确的统一命名格式:行人ID(5)_C摄像头ID(5)_时间(可选)_序号(3)_.jpg,如:00001_C10001_201809271330_001.jpg
但是同事A容易把’C’打成’c’,把’_’打成‘__’等,这些错误会导致提取关键字的时候发生错误,比如我们用split函数,以’_’为分割字符来分割文件名,提取它的行人ID信息的时候,某一个文件名的‘_’变成了‘__’就会导致读取失败或者错误;或者使用正则表达式pattern = re.compile(r'([-\d]+)_C(\d+)')来获取行人ID和摄像头ID的时候,某个文件的’c’和’C’混淆了,也会导致正则表达式无法提取到对应的信息。
分析:
从几千设置几万的数据集中手动查找这些命名错误的文件肯定是不可行的,但是如果编写程序检查命名格式,再遇到错误名字的时候,又会使得整个程序停下,虽然这时候可以定位到那个命名错误的文件,但是如果这样的文件有20个,那你就得运行程序20次,况且,到底有多少个错误命名的文件,你通常事先不会知道,那么有什么办法呢?
异常处理!
当出现异常的时候,你可以观察一下出现的是什么异常,然后针对该异常的情况,采取相应的措施,在本案例中,我们显然是想要跳过该异常文件,继续检查整个文件夹中的所有文件,那么我们就可以这样写:
代码:
check_data.py
import os
import shutil
#设置总路径
PATH = 'E:/HGTX347/data2/'
#获取所有文件路径
def file_name(file_dir):
L=[]
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.jpg':
L.append(file)
return L
def remove_time(i):
if i < length:
id = L[i].split('_',4)
print (id)
#文件重命名
os.rename(PATH+file_dir+id[0]+'_'+id[1]+'_'+id[2]+'_'+id[3],PATH+new_file_dir+id[0]+'_'+id[1]+'_'+id[2]+'.jpg')
#设置文件夹名字,里面有需要改名的文件
file_dir="query/"
new_file_dir = "temp/"
#获取文件路径,存放于数组L中
L = file_name(file_dir)
#获取数组长度(图片数量)
length = len(L)
i=0
for i in range(length):
try:
remove_time(i)
except FileExistsError: #根据控制台提示的Error类型来设置
continue #如果发现异常,跳过这个文件,继续
print('finished processing'+str(i+1)+' pitures')
这样一来,原来的文件夹下剩下的文件就都是不符合条件的命名错误的文件了,这时候就可以一个一个地改名,方便快捷~