python数据分析和可视化基础
第二十七章:python文件操作
(一)python文件操作学习目标
目标
- 文件的概念
- 文件的基本操作
- 文件/文件夹的常用操作
- 文本文件的编码方式
(二)文件的概念
文件的概念和作用
计算机的 文件,就是存储在某种 长期储存设备 上的一段 数据。长期存储设备包括:硬盘、U盘、移动硬盘、光盘…
文件的作用是将数据长期保存下来,在需要的时候使用
文件的存储方式
在计算机中,文件是以二进制的方式保存在磁盘上的
文本文件和二进制文件
文本文件
- 可以使用文本编辑软件查看
- 本质上还是二进制文件
- 例如:python 的源程序
二进制文件
- 保存的内容 不是给人直接阅读的,而是 提供给其他软件使用的
- 例如:图片文件、音频文件、视频文件等等
- 二进制文件不能使用文本编辑软件 查看
(三)文件的基本操作
3.1操作文件的套路
在 计算机 中要操作文件的套路非常固定,一共包含三个步骤:
-
打开文件
-
读、写文件
- 读 将文件内容读入内存
- 写 将内存内容写入文件
- 关闭文件
3.2 操作文件的函数/方法
在Python中要操作文件需要记住1个函数和3个方法
open 函数负责打开文件,并且返回文件对象
read/write/close 三个方法都需要通过文件对象来调用
3.2.1 open方法打开文件
open
: 函数的第一个参数是要打开的文件名(文件名区分大小写)
。如果文件 存在
,返回 文件操作对象
。如果文件 不存在
,会 抛出异常
f = open(‘test.txt’) # 一般配合打开方式使用 例如 w
完整的语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
#file 包含文件名的字符串,可以是绝对路径,可以是相对路径。
#mode 一个可选字符串,用于指定打开文件的模式。默认值 r 表示文本读。
#encoding 文本模式下指定文件的字符编码
3.2.2 write方法写入文件
write
:方法负责 写入文件
#写入文件
f = open("test.txt","w") #打开文件,w模式(写模式),文件不存在就新建
f.write("hello world,I am here!") #将字符串写入文件中
f.close() #关闭文件
3.2.3 read方法打开文件
read
:方法可以一次性 读入
并 返回
文件的 所有内容
#读:read方法,默认读取全部,(5)读取指定的字符,开始时定位在文件头部,每执行一次向后移动指定字符数
f = open("test.txt","r")
text = f.read(5) #一次读五个字符
print(text)
print('-'*30)
text = f.read() #读取全部
print(text)
f.close()
3.2.4 close方法打开文件
close
:方法负责 关闭文件
f.close()
如果 忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
注意:方法执行后,会把 `文件指针` 移动到 `文件的末尾`
# 1.打开文件
file = open("1.py",encoding="utf-8")
# 2.读取文件
text = file.read()
print(text)
# 3.关闭文件
file.close()
提示:
在开发中,通常会先编写 打开 和 关闭 的代码,再编写中间针对文件的 读/写 操作!
3.2.4 文件指针(知道)
文件指针 标记
从哪个位置开始读取数据
第一次打开 文件时,通常 文件指针会指向文件的开始位置
当执行了 read 方法后,文件指针会移动到 读取内容的末尾.
默认情况下会移动到 文件末尾
思考:
如果执行了一次 read 方法,读取了所有内容,那么再次调用read 方法,还能够获得到内容吗?
答案: 不能
第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容
# 1.打开文件
file = open("1.py",encoding="utf-8")
# 2.读取文件
text = file.read()
print(text)
print(len(text))
print("_" * 50)
text = file.read() # 再次调用不会读取到任何的内容
print(text)
print(len(text)) #长度为0
# 3.关闭文件
file.close()
907
__________________________________________________
0
3.2.5 打开文件的方式
open 函数默认以 只读方式 打开文件,并且返回文件对象
语法如下:
f = open("文件名","访问方式")
所有以 r 开头的,如果文件不存在,则报错,不会新建文件;文件指针都会放在文件的开头;
所有以 w 开头的,如果文件不存在,则自动创建;文件指针都会放在文件的开头;每次执行该函数时会覆盖掉源文件
所有以 a 开头的,如果文件不存在,则自动创建;文件指针会放在文件的末尾用于附加数据,不会覆盖数据
# 1.打开文件
file = open("1.py",'w')
# 写入文件
file.write("hello world")
print
# 关闭文件
file.close()
提示
频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写 的方式来操作文件
(四)按行读取文件内容
read 方法默认会把文件的 所有内容 一次性读取到内存
如果文件太大,对内存的占用会非常严重
4.1 readiine 一次只读一行内容
readline 方法可以一次读取一行内容方法执行后,会把文件指针移动到下一行,准备再次读取
读取大文件的正确姿势
# 打开文件
file = open("4.py")
while True:
# 读取一行内容
text = file.readline() #读取一行内容 文件指针 移动到下一行
# 判断是否读到内容
if not text:
break
# 每读取一行的末尾已经有了一个\n
print(text, end="")
# 关闭文件
file.close()
4.2 readlines 一行行读取全部文件
就像read没有参数时一样,readlines可以按照行
的方式把整个文件中的内容进行一次性的读取,并且返回的是一个列表
,其中每一行的数据为一个元素
f = open("test.txt","r")
text = f.readlines() # 一次性读取全部文件返回一个列表,每行一个字符串
print(text)
#['hello world,I am here!\n', 'hello world,I am here!\n', 'hello world,I am here!\n', 'hello world,I am here!\n',
i = 1
for temp in text:
print("%d:%s"%(i,temp))
i += 1
f.close()
(五)文件读写函数综合应用
文件读写案例 --复制文件
目标
用代码的方式,来实现文件复制过程
5.1 小文件复制
打开一个已有文件,读取完整内容,并写入到另外一个文件
# 打开文件
file_read = open("4.py","r")
file_write = open("5.py","w")
# 读写文件
text = file_read.read()
file_write.write(text)
# 关闭文件
file_read.close()
file_write.close()
5.2大文件复制
打开一个已有文件,逐行读取的容,并顺序写入到另外一个文件
# 打开文件
file_read = open("4.py","r")
file_write = open("5.py","w")
# 读写文件
while True:
text = file_read.readline()
if not text:
break
file_write.write(text)
# 关闭文件
file_read.close()
file_write.close()
with open 管理器
解决经常会忘记关闭文件句柄,造成资源浪费,所以处理文件是往往使用 with 语句进行上下文管理。使用with语句可以创建一个上下文管理器,并在代码块执行完毕后自动关闭文件,无需手动调用close()方法。
with open(文件名, 模式) as 文件对象:
文件对象.方法()
with open('test.txt', 'r',encoding="utf-8") as f:
print(f.read())
# 一般写法
f = open('test.txt','r',encoding="utf-8")
f.read()
路径问题
绝对路径:它指定了文件在电脑中的具体位置,以 windows 电脑为例:
c:\user\liyue\python.py
相对路径:一般是指相对当前脚本的路径,
相对路径的写法:
# 同级目录可以直接读取
test.txt
# 在上级目录的话需要../返回上一层目录读取
../test.txt
with open(file=r"a.txt",mode="r",encoding="utf-8") as fb:
with open(file=r"../a.txt",mode="r",encoding="utf-8") as fb:
with open(file=r"c:\user\liyue\a.txt",mode="r",encoding="utf-8") as fb:
seek 方法:通过文件对象的 seek 方法可以移动文件句柄
seek 方法接收两个参数:
offset 表示偏移指针的字节数
whence 表示偏移参考,默认为 0
0 表示偏移参考文件的开头,offset 必须是 >=0 的整数
1 表示偏移参考当前位置,offset 可以是负数
2 表示偏移参考文件的结尾,offset 一般是负数
with open('test.txt', 'r', encoding='utf-8') as f:
print(f.read(3))
# 跳转到文件开头
f.seek(0)
# 再读取第一个字
print(f.read(1))
#响应:
爱死你
爱
文件的编码处理
在处理文本文件时,需要考虑文件的编码格式。Python提供了多种编码处理方式,常见的有:
ascii:ASCII编码,适用于英文文本。
utf-8:UTF-8编码,适用于多种语言的文本。
latin-1:Latin-1编码,适用于西欧语言的文本。
在打开文件时,你可以指定文件的编码格式。
with open('file.txt', 'r', encoding='utf-8') as file:
# 处理文件内容
(六)文件/目录的常用管理操作
在 终端/文件浏览器
中可以执行常规的 文件/目录
管理操作,例如:创建、重命名、删除、改变路径、查看目录内容
在 Python 中,如果希望通过程序实现上述功能,需要导入os模块
.
6.1 文件操作
import os
os.rename("python.txt","python3.txt")
import os
os.remove(“python.txt”)
6.2 目录操作
提示:文件或者目录操作都支持 相对路径 和绝对路径
import os
os.mkdir(“张三”)
import os
os.getcwd()
import os
os.chdir("../")
6.3 文本文件的编码格式(科普)
文本文件存储的内容是基于字符编码的文件,常见的编码有 ASCII 编码,UNICODE 编码等
- Python 2.x默认使用 ASCII 编码
- Python 3.x默认使用 UTF-8 编码
ASCII 编码 和 UNICODE 编码
- ASCII 编码 计算机中只有256个ASCII字符
- 一个 ASCII 在内存中占用1个字节 的空间 。
- 8个0/1的排列组合方式一共有256种,也就是2**8
UTF-8 编码格式
- 计算机中使用 1~6 个字节 来表示一个 UTF-8 字符,涵盖了地球上几乎所有地区的文字
- 大多数汉字会使用3个字节 表示
- UTF-8是UNICQDE编码的一种编码格式
6.4 Ptyhon 2.x 中如何使用中文
Python 2.x默认使用 ASCII 编码格式
Python 3.x默认使用 UTF-8 编码格式
在 Python 2.x文件的 第一行 增加以下代码,解释器会以 utf-8 编码来处理 python 文件
# *-* coding:utf8 *—*
这方式是官方推荐使用的!
也可以使用
# coding=utf8
unicode 字符串
在 Python 2.x中,即使指定了文件使用 UTF-8 的编码格式,但是在遍历字符串时,仍然会 以字节为单位遍历 字符串
要能够 正确的遍历字符串,在定义字符串时,需要 在字符串的引号前,增加一个小写字母 u,告诉解释器这是一个 unicode 字符串(使用 UTF-8 编码格式的字符串)
# *_*coding:utf8
#引号前面的u告诉解释器这是一个utf8编码格式的字符串
hello str = u"hello世界"
print(hello str)
for c in hello_str:
print(c)
6.5 eval 函数
eval()函数十分强大 --将字符串 当成 有效的表达式 来求值 并 返回计算结果
# 基本的数学计算
In [1]: eval("1 + 1")
0ut[1]:2
# 字符串重复
In [2]:eval("'*'* 10")
0ut [2]:"**********"
# 将字符串转换成列表
In[3]:type(eval("[1,2,3,4,5]"))
0ut[3]: list
#将字符串转换成字典
In[4]:type(eval("{'name':'xiaoming','age': 18}"))
0ut[4]: dict
案例-计算器
需求
1.提示用户输入一个 加减乘除混合运算
2.返回计算结果
input_str = input("请输入算术题:")
print(eval(input_str))
不要滥用 eval
在开发时千万不要使用 eval直接转换 input的结果
import ('os').system('ls')
等价代码
import os
0s.system("终端命令")
执行成功,返回 0
执行失败,返回错误信息
请输入算术题:import ('os').system('rm aaa')
第二十八章:python模块的操作
(一)模块的概念
模块是 Python 程序架构的一个核心概念
每一个以扩展名 py结尾的Python 源代码文件都是一个 模块
模块名
同样也是一个 标识符
,需要符合标识符的命名规则
在模块中定义的 全局变量、函数、类
都是提供给外界直接使用的 工具
模块 就好比是 工具包
,要想使用这个工具包中的工具,就需要先 导入
这个模块
(二)模块的导入
在 Python 中用 import 或者 from…import 来导入相应的模块:
将整个模块
(somemodule) 导入,格式为: import somemodule
从某个模块中导入某个函数
,格式为: from somemodule import somefunction
从某个模块中导入多个函数
,格式为: from somemodule import firstfunc, secondfunc, thirdfunc
将某个模块中的全部函数
导入,格式为: from somemodule import *
语法格式:
import random # 引入随机数
x = random.randint(0, 2) # 随机生成 0、1、2 中的一个数字,赋值给变量 x
print(x)
不推荐的导入方式
import 模块1,模块2
提示:在导入模块时,每个导入应该独占一行
import 模块1 # 推荐
import 模块2
(三)函数的调用
从某个模块导入某个函数后,调用该函数的语法格式为:模块名称.函数名称(变量)
比如,Python 中的 randint 用来生成指定范围内的随机整数,在使用 randint 之前,需要调用 random 库。该函数的语法格式为 random.randint(x, y),参数 x 和 y 代表生成随机数的区间范围,生成的随机数包括 x 和 y。
通过 模块名. 使用模块提供的工具 --- 全局变量、函数、类
random.randint(x, y)
调用实例
hm_01_测试模块1
# 全局变量
title = "模块1"
# 函数
def say_hello():
print("我是 %s" % title)
# 类
class Dog(object):
pass
hm_02_测试模块2
# 全局变量
title = "模块2"
# 函数
def say_hello():
print("我是 %s" % title)
# 类
class Dog(object):
pass
import导入模块
import hm_01_测试模块1 #导入模块
import hm_02_测试模块2
hm_01_测试模块1.say_hello() # 模块名称.函数名称(变量)
hm_02_测试模块2.say_hello()
dog = hm_01_测试模块1.Dog()
print(dog)
cat = hm_02_测试模块2.Cat()
print(cat)
(四)模块的别名
使用 as 指定模块的别名
如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用
import 模块名1 as 模块别名
注意:模块别名 应该符合 大驼峰命名法
import hm_01_测试模块1 as DogModule #导入模块 使用别名
import hm_02_测试模块2 as CatModule
DogModule.say_hello() # 别名.函数名称(变量)
CatModule.say_hello()
dog = DogModule.Dog()
print(dog)
cat = CatModule.Cat()
print(cat)
(五)form…import导入模块
如果希望 从某一个模块
中,导入部分 工具
,就可以使用 from…import 的方式
import 模块名 是 一次性
把模块中 所有工具全部导入
,并且通过 模块名/别名
访问
#从 模块 导入 某一个工具
from 模块名1 import 工具名
有什么好处?
导入之后
。不需要 通过 模块名.访问
。可以直接使用 模块提供的工具 - - - 全局变量、函数、类
注意:
**如果两个模块,存在同名的函数,那么后导入模块的函数,会覆盖掉先导入的函数**
from hm_01_测试模块1 import Dog #导入模块的函数或者类
from hm_02_测试模块2 import say_hello
say_hello() # 直接使用其他模块的函数
dog = .Dog() # 直接使用其他模块的对象
print(dog)
注意事项
开发时 import代码应该统一写在 代码的顶部,更容易及时发现冲突
一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名
from hm_01_测试模块1 import say_hello as model2_say_hello # 给其中一个工具起一个别名
from hm_02_测试模块2 import say_hello # 后导入模块的函数,会覆盖掉先导入的函数
say_hello()
model2_say_hello()
(六)from…import*(知道)
从 模块 导入 所有工具
from 模块名1 import *
注意
这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查
(七)模块(包)的下载
在 Python 中,模块(包)是一组函数、类、变量或语句的集合,可以被其他程序引用。Python 拥有丰富的模块库,但是在使用时有时需要下载其他的模块。
3.1 使用 pip 下载模块(包)
pip 是 Python 的包管理工具,可以用于安装、升级和卸载 Python 包。使用 pip 下载模块非常简单:右键开始菜单栏、选择“运行”、输入“cmd”并点击“确定”、在命令提示行中输入以下命令并回车:
pip install name
或者
pip install name==版本号
pip install pandas==1.0.3
3.2 使用 PyCharm 下载模块(包)
- 打开 PyCharm,进入项目界面;
- 点击菜单栏上的 File -> Settings;
- 在弹出的窗中,选择 Project ->Project Interpreter;
- 接下来点击上面界面左上角的“+”;
然后在搜索框中搜索需要安装的第三方库,然后点击界面左下角的“Install Package”进行安装即可。
3.3 在 PyCharm 代码编辑区下载模块(包)
点击底部标红的需要下载的模块名称,在悬浮的框中继续点击“Install package 包名”,即可进行模块的安装。
(八)模块的搜索顺序[扩展]
Python 的解释器在 导入模块 时,会:
- 搜索 当前目录 指定模块名的文件,如果有就直接导入
- 如果没有,再搜索 系统目录
在开发时,给文件起名不要和系统的模块文件重名
Python 中每一个模块都有一个内置属性__file__可以 查看模块 的 完整路径
示例
import random
#生成一个 0~10 的数字
rand = random.randint(0,10)
print(rand)
注意:如果当前目录下,存在一个random.py 的文件,程序就无法正常执行了! 这个时候, Python 的解释器会加载当前目录下的random.py 而不会加载系统的random模块
import random
print(random.__file__)
D:\python312\Lib\random.py
(九)原则 – 每一个文件都可以被导入
- 一个 独立的 Python 文件 就是一个 模块
- 在导入文件时,文件中 所有没有任何缩进的代码 都会被执行一遍!
实际开发场景:
在实际开发中,每一个模块都是独立开发的,大多都有专人负责,开发人员 通常会在 模块下方 增加一些测试代码,仅在模块内使用,而被导入到其他文件中不需要执行
9.1 __name_属性
name 属性可以做到测试模块的代码
只在测试情况下被运行,而在 被导入时不会被执行
!
__name__是Python 的一个内置属性,记录着一个字符串
- 如果 是被其他文件导入的,__name__就是
模块名
- 如果 是当前执行的程序 __name__是 main
hm_09_name__模块
# 全局变量、函数、类,注意:直接执行的代码不是向外界提供的工具!
def say_hello:
print("你好,你好我是say_hello")
# 文件被导入时,能够直接执行的代码不需要被执行!
print("小明开发的这个模块")
say_hello()
hm_09_name__测试导入
import hm_09_name__模块
print("*" * 50)
小明开发的这个模块
你好,你好我是say_hello
**************************************************
上面测试代码没有调用就输出出来了,所以这些不需要调用就执行的内容是不希望被输出的,print(name)如果是当前程序执行的 name__就是__main,被其他文件导入的,__name__就是 模块名
# 全局变量、函数、类,注意:直接执行的代码不是向外界提供的工具!
def say_hello():
print("你好,你好我是say_hello")
# 文件被导入时,能够直接执行的代码不需要被执行!
if __name__ == '__main__':
# 文件被导入时,能够直接执行的代码不需要被执行!
print("小明开发的这个模块")
say_hello()
(十)python的包
概念
- ·包 是一个 包含多个模块 的 特殊目录
- 目录下有一个 特殊的文件__init__.py
- 包名的 命名方式 和变量名一致,小写字母 +.
好处
- 使用 import 包名 可以一次性导入 包 中所有的模块
案例演练
-
新建一个 hm_message 的包
-
在目录下,新建两个文件 sendmessage和receive_message
-
在 send_message 文件中定义一个 send 函数
-
在 receive_message 文件中定义一个 receive 函数
-
在外部直接导入 hm_message 的包
__init__·py 要在外界使用包中的模块,需要在__init__.py 中指定对外界提供的模块列表
# 从 当前目录 导入 模块列表
from .import send message
from .import receive message
如果我们在开发中希望把多个模块打包,就可以使用这种方式
1.新建一个 hm_message 的包
或者
2.在目录下,新建两个文件 send_message和receive_message
3. 在 send_message 文件中定义一个 send 函数
def send(name):
print("发送给 %s" % name)
4.在 receive_message 文件中定义一个 receive 函数
def receive():
return "这是来自100xxx的短信"
5.在外部直接导入 hm_message 的包
import hm_message
6.需要在__init__.py 文件中指定对外界提供的模块列表
from . import send_message
from . import receive_message
7.主程序才能使用send_message和receive_message
import hm_message
hm_message.send_message.send("liyeu")
rec = hm_message.receive_message.receive()
print(rec)
(十一)发布模块(知道)
如果希望自己开发的模块,分享 给其他人,可以按照以下步骤操作
10.1 制作发布压缩包步骤
- 创建 setup.py
from distutils.core import setup
setup(name="hm message",#包名
version="1.0", # 版本
description="itheima's 发送和接收消息模块", # 描述信息
long_description = "完整的发送和接收消息模块", # 完整描述信息
author="itheima",#作者
author_email="itheima@itheima.com", #作者邮箱
url="www.itheima.com",#主页
py_modules=(["hm_message.send_message",
"hm_message.receive_message"])
有关字典参数的详细信息,可以参阅官方网站:
https://docs.python.org/2/distutils/apiref.html
- 构建模块
$python3 setup.py build
- 生成发布压缩包
$python3 setup.py sdist
10.2 安装模块
把上面制作的压缩包分享给别人以后怎么使用这个压缩包
$ tarf-zxvf hm message-1.0.tar.gz
$sudo python3 setup.py install
卸载模块
直接从安装目录下,把安装模块的 目录 删除就可以
$ cd /usr/local/lib/python3.5/dist-packages/
$sudo rmr hm message*
第二十九章:抛出异常
目标
- 异常的概念
- 捕获异常
- 异常的传递
- 自定义异常
(一)异常的概念
程序在运行时,如果 Python 解释器 遇到 到一个错误会停止程序的执行,并且提示一些错误信息,这就是异常
程序停止执行并且提示错误信息 这个动作,我们通常称之为: 抛出(raise)异常
程序开发时,很难将 所有的特殊情况 都处理的面面俱到,通过 异常捕获 可以针对突发事件做集中的处理,从而保证程序的 稳定性和健壮性
(二)捕获异常
简单的捕获异常语法
在程序开发中,如果 对某些代码的执行不能确定是否正确,可以增加 try(尝试)来 捕获异常
捕获异常最简单的语法格式:
try:
尝试执行的代码
except:
出现错误的处理
try 尝试,下方编写要尝试代码,不确定是否能够正常执行的代码
except 如果不是,下方编写尝试失败的代码
不管到底有没有错,程序在执行完捕获的代码后还会接着向下执行
简单异常捕获演练 --要求用户输入整数
try:
#提示用户输入一个数字
# 不能确定正确执行的代码
num = int(input("请输入数字:"))
except:
# 错误的处理代码
print("请输入正确的数字")
(三)错误类型捕获
在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
语法如下:
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except(错误类型2,错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s"% result)
当Python 解释器 抛出异常 时,最后一行错误信息的第一个单词,就是错误类型
异常类型捕获演练–要求用户输入整数
需求
1.提示用户输入一个整数
2.使用 8除以用户输入的整数并且输出
try:
# 提示用户输入一个整数
num = int(input("输入一个整数:"))
# 使用 8 除以用户输入的整数并且输出
result =8 / num
print(result)
except ZeroDivisionError:
print("除θ错误")
except ValueError:
print("请输入正确的整数")
(四)捕获未知错误
在开发时 要预判到所有可能出现的错误,还是有一定难度的,如果希望程序 无论出现任何错误,都不会因为Python 解释器 抛出异常而被终止,可以再增加一个except
语法如下:
except Exception as result:
print("未知错误 %s"% result)
try:
# 提示用户输入一个整数
num = int(input("输入一个整数:"))
# 使用 8 除以用户输入的整数并且输出
result =8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确的整数")
except Exception as result:
print("未知错误 %s" % result)
(五)异常捕获完整语法
在实际开发中,为了能够处理复杂的异常情况,完整的异常语法如下:
提示:
有关完整语法的应用场景,在后续学习中,结合实际的案例会更好理解
现在先对这个语法结构有个印象即可
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except 错误类型2:
#针对错误类型2,对店的代码处理
pass
except(错误类型3,错误类型4):
# 针对错误类型3 和 4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
# 没有异常才会执行的代码
pass
finally:
# 无论是否有异常,都会执行的代码
print("无论是否有异常,都会执行的代码")
- else 只有在没有异常时才会执行的代码
- finally 无论是否有异常,都会执行的代码
之前一个演练的 完整捕获异常 的代码如下:
try:
# 提示用户输入一个整数
num = int(input("输入一个整数:"))
# 使用 8 除以用户输入的整数并且输出
result =8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确的整数")
except Exception as result:
print("未知错误 %s" % result)
else:
print("尝试成功")
finally:
print("无论是否有异常,都会执行的代码")
print("*" * 50)
没有错误的时候执行效果
输入一个整数:1
8.0
尝试成功
无论是否有异常,都会执行的代码
**************************************************
出现错误的执行效果
输入一个整数:0
除0错误
无论是否有异常,都会执行的代码
**************************************************
(五)异常的传递
异常的传递 --当 函数/方法执行出现异常,会将异常传递 给 函数/方法 的调用一方,如果传递到主程序,仍然没有异常处理,程序才会被终止
提示
- 在开发中,可以在主函数中增加 异常捕获
- 而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获 中
- 这样就不需要在代码中,增加大量的 异常捕获,能够保证代码的整洁
需求
- 定义函数 emo1()提示用户输入一个整数并且返回
- 定义函数 demo2()调用 demo1()
- 在主程序中调用 demo2()
1 def demo1():
2 return int(input("请输入一个整数:"))
3 def demo2():
4 return demo1()
5
6 print(demo2())
将异常传递给函数/方法的调用一方 从第2行开始传递到4,6行
在主函数中增加异常捕获以后 主函数中调用的demo2()函数,出现异常,都会传递到主函数的异常捕获中,不需要在上面增加异常捕获了
def demo1():
return int(input("请输入一个整数:"))
def demo2():
return demo1()
# 利用异常的传递性 在主程序捕获异常
try:
print(demo2())
except ValueError:
print("请输入正确的整数")
except Exception as result:
print("未知错误 %s" % result)
(六)抛出 raise 异常
应用场景
在开发中,除了代码执行出错 ,Python 解释器会抛出异常之外,还可以根据应用程序特有的业务需求主动抛出异常。
示例
提示用户输入密码,如果 长度少于 8,抛出 异常
注意
当前函数 只负责 提示用户输入密码,如果 密码长度不正确,需要其他的函数进行额外处理,因此可以 抛出异常,由其他需要处理的函数 捕获异常
抛出异常
Python 中提供了一个Exception 异常类,在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
- 创建一个 Exception 的对象
- 使用 raise 关键字 抛出 异常对象
需求
- 定义 input_password 函数,提示用户输入密码
- 如果用户输入长度<8,抛出异常
- 如果用户输入长度 >=8,返回输入的密码
def input_password():
password = input("Enter your password: ")
if len(password) >= 8:
return password
print("主动抛出异常")
# 3.如果 <8 主动抛出异常
# 1> 创建异常对象
ex = Exception("密码长度不够")
# 2>主动抛出异常
raise ex
try:
print(input_password())
except Exception as ex:
print(ex)