Python异常的排除,以及对Python标准库的基本认知。
异常
错误与异常
如果我们把print
拼错为Print
,Python会抛出(Raise)一个语法错误。
示例程序块如下:
运行结果如下:
1
2
3
4
|
Traceback (most recent call last):
File "error.py", line 1, in <module>
Print("Hello World")
NameError: name 'Print' is not defined
|
在上述示例中,NameError
错误被抛出,同时Python检测错误发生的位置。这就是一个错误处理器(Error Handler)为我们的错误所做的事情。
处理异常
我们可以通过使用try...except
来处理,一般来说,我们把普通的语句放在try
代码块中,将我们的错误处理器代码放在except
代码块中。
示例程序块如下:
1
2
3
4
5
6
7
8
9
10
11
|
try:
text = input('Enter something -->')
except EOFError:
print('Why did you do an EOF on me?')
except KeyboardInterrupt:
print('You cancelled the operation.')
else:
print('You entered {}'.format(text))
|
运行结果如下:
1
2
3
4
5
6
7
8
9
|
# Press ctrl + d
$ python exceptions_handle.py
Enter something --> Why did you do an EOF on me?
# Press ctrl + c
$ python exceptions_handle.py
Enter something --> ^CYou cancelled the operation.
$ python exceptions_handle.py
Enter something --> No exceptions
You entered No exceptions
|
在上述示例中,我们将所有可能引发异常或者错误的语句都放在了try
代码块中,并将相应的错误或者异常的处理器(Handler)放在except
子句或者代码块中。其中except
子句可以处理某种特定的错误或者异常,或者是一个在括号中列出的错误或者异常。如果没有提供错误或者异常的名称,那么它将处理所有的错误和异常。
注意:
- 必须至少有一句
except
字句与每一句try
字句相关联,否则try
代码块无意义。
- 若没有任何错误或者异常被处理,那么将调用Python默认处理器,它会利用终端程序打印出错误信息;
else
语句与try...except
代码块相关联,其作用是再没有发生异常的时候执行。
抛出异常
在Python中,可以通过raise
语句来引发一次异常,具体的方法是提供错误名或者异常名以及要抛出(Thrown)异常的对象。
注意:我们能够引发的错误或者异常必须是直接或者间接从属于Exception(异常)
类的派生类。
示例程序块如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class ShortInputException(Exception):
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input('Enter something -->')
if len(text) < 3:
raise ShortInputException(len(text), 3)
except EOFError:
print('Why did you do an EOF on me?')
except ShortInputException as ex:
print(('ShortInputException: The input wa ' + '{0} long, expected at least {1}').format(ex.length, ex.atleast))
else:
print('No exception was raised.')
|
运行结果如下:
1
2
3
4
5
6
|
PS E:\sublime text 3 files\python3> python exceptions_raise.py
Enter something -->a
ShortInputException: The input wa 1 long, expected at least 3
PS E:\sublime text 3 files\python3> python exceptions_raise.py
Enter something -->abc
No exception was raised.
|
注意:
- 在本例中,我们创建了名为
ShortInputException
的异常类型。它包含两个字段:①获取给定输入文本长度的length
②程序期望的最小长度atleast
;
- 在
except
子句中,我们提及了错误类,并将该类存储as
为相应的错误名或者异常名。这类似于函数调用中的形参和实参;
- 在上述示例中,我们在
except
子句中使用异常对象的length
和atleast
字段来向用户打印一条合适的信息。
Try…Finally
在Python中,我们可以通过finally
代码块来确认文件对象是否被正确关闭。
示例程序块如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import sys
import time
f = None
try:
f = open("poem.txt")
while True:
line = f.readline()
if len(line) == 0:
break
print(line, end='')
sys.stdout.flush()
print("Press ctrl+c now")
time.sleep(2) #运行间隔为2s
except IOError:
print("Could not find file poex.txt")
except KeyboardInterrupt:
print("!! You cancelled the reading from the file.")
finally:
if f:
f.close()
print("(Cleaning up: Closed the file)")
|
运行结果如下:
1
2
3
4
5
6
7
|
PS E:\sublime text 3 files\python3> python exceptions_finally.py
Programing is fun
Press ctrl+c now
When the work is done
Press ctrl+c now
!! You cancelled the reading from the file.
(Cleaning up: Closed the file)
|
注意:
- 在上例中,我们通过使用
time.sleep
函数任意在每打印一行后插入两秒的休眠时间;
- 在程序运行过程中,通过按下
ctrl + c
来中断或者取消程序;
- 在程序退出之前,
finally
语句得到执行,文件对象被关闭;
- 我们在
print
之后使用了sys.stout.flush()
,以便它能被立即打印到屏幕上。
with
语句
在上文中,我们在try
块中获取资源,然后再finally
块中释放资源是一种常见模式,此外,我们还有一个with
语句使得这一过程可以以另一种姿势来完成。
示例程序块如下:
1
2
3
|
with open("poem.txt") as f:
for line in f:
print(line, end='')
|
运行结果如下:
1
2
3
4
|
Programing is fun
When the work is done
if you wanna make your work also fun:
use PYTHON!
|
注意:
- 在此例中,我们使用
open
函数与with
语句,而我们将关闭文件的操作交由with open
来完成;
- 实际上,
with
语句使用的协议会获取由open
语句返回的对象,再本案例中是thefile;
- 程序再代码块开始之前调用
thefile.__enter__
函数,并且总会在代码块执行完后调用thefile.__exit__
;
- 在使用
finally
代码块中,应该格外留心__exit__
方法的自动操作,因为这样可以帮助我们便面重复显式使用try...finally
语句。
标准库
Python标准库中包含了大量有用的模块,可以在Python安装包中附带的文档中库概览(Library Reference)部分可以查找到所有模块的全部细节。
sys
模块
sys
模块中半酣了一些特定系统的功能,下面示例给出其相关用法。
示例运行结果如下:
1
2
3
4
5
6
7
8
|
PS E:\sublime text 3 files\python3> python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=6, micro=3, releaselevel='final', serial=0)
>>> sys.version_info.major == 3
True
|
注意:从上例我们可以看出,sys
模块包含一个version_info
元祖,它提供给我们版本信息。
日志模块
当我们需要调试(Debugging)程序时,我们可以通过logging
模块来实现。
示例程序块如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import os
import platform
import logging
if platform.platform().startswith("Windows"):
logging_file = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'), 'test.log')
else:
logging_file = os.path.join(os.getenv('HOME'), 'test.log')
print("Logging to", logging_file)
logging.basicConfig(
level = logging.DEBUG,
format = '%(asctime)s : %(levelname)s : %(message)s',
filename = logging_file,
filemode = 'w',
)
logging.debug("Start of the program")
logging.info("Doing something")
logging.warning("Dying now")
|
运行结果如下:
1
2
3
4
5
6
|
PS E:\sublime text 3 files\python3> python stdlib_logging.py
Logging to C:\Users\Administrator\test.log
PS E:\sublime text 3 files\python3> cat C:\Users\Administrator\test.log
2018-04-26 22:57:43,345 : DEBUG : Start of the program
2018-04-26 22:57:43,345 : INFO : Doing something
2018-04-26 22:57:43,345 : WARNING : Dying now
|
注意:
- 上述示例使用了三款标准库中的模块,分别为:①
os
模块用于和操作系统交互 ②platform
模块用于获取我们使用的操作系统的信息 ③logging
模块用来记录(Log)信息;
- 在示例中,首先通过检查
platform.platform()
的返回值来确认我们使用的操作系统,如果是Windows,我们就找出来其主驱动器(Home Drive),主文件夹(Home Folder)以及我们希望存储信息的文件名,并将这三个部分汇聚一起,这样我们便得到了此文件的全部位置信息。对其他平台而言,我们只需知道主文件夹位置便可以获得文件的全部位置信息;
- 其次,我们使用
os.path.join()
函数将三部分位置信息聚合到一起;
- 再者,我们配置
logging
模块,从而让它以特定的格式将所有信息写入我们制定的文件内;
- 最后不论这些信息时用来调试,提醒或者警告以及其他信息,我们的日志文件
test.log
都会将其聚合并记录,这样,我们就可以知道自己的程序在运行过程中发生了什么事情。
更多内容,请参考Python Module of the Week或者Python的官方文档。