python入门篇-day07-异常与模块

异常

介绍

概述

我们把程序中出现的所有非正常情况, 统称为: 异常. 俗称叫: Bug.

程序默认处理异常方式

程序会将异常的类型, 产生的原因, 以及异常的位置, 打印到控制台上.并终止程序的执行.

问: 如何实现, 解决异常之后, 让程序继续往下执行呢?答: 可以通过 捕获异常: try.except.finally 这种方式来实现.

演示异常

# 你可能会遇到的一些异常.
print(10 // 0)            # 除数不能为 0, ZeroDivisionError
​
src_f = open('1.txt', 'r')  # 文件不存在, FileNotFoundError
print(src_f)
​
print('看看我执行了吗!')

捕获异常

概述

指的是 try.except.finally 这个语法, 即: 手动处理异常.

特点

手动处理之后, 程序会继续向下执行.

格式

try: 里边写可能出问题的代码except: 如果出问题了, 这里写的是 处理方式

格式解释

  1. 先执行try中的内容, 看有无问题.

  2. 有问题, 则会立即跳转到 except语句中 执行.

  3. 无问题, 则不会执行 except中的内容.

  4. 无论是否有问题, 处理之后, 程序都会自动向下执行.

演示

# 需求: 尝试去读取 1.txt 文件中的数据, 如果文件不存在, 我们就创建.
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    src_f = open('1.txt', 'r')  # 这行代码有Bug
    print('----- try 2 -----')
    print(src_f)
except:
    # 这里写的是, 出问题后的解决方案
    # print('哎呀, 程序出问题了!')
    # 走这里, 说明文件不存在, 我们就创建它.
    src_f = open('1.txt', 'w')
    print('----- except -----')
​
print('看看我执行了吗!')

捕获指定异常

格式

try:
    里边写可能出问题的代码
except [Exception as e]:                          # 这里的[]表示 可选
    如果出问题了, 这里写的是 处理方式

演示

# 需求: 尝试去读取 1.txt 文件中的数据, 如果文件不存在, 我们就创建.
# 场景1: 捕获指定的异常.
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    src_f = open('1.txt', 'r')  # 这行代码有Bug
    print('----- try 2 -----')
except FileNotFoundError:
    # 这里写的是, 出问题后的解决方案
    print('----- except 1 -----')
    src_f = open('1.txt', 'w')
    print('----- except 2 -----')
​
​
# 场景2: 捕获异常时, 异常的类型 和 异常出现的类型不匹配, 则: 捕获不到该异常.
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    src_f = open('1.txt', 'r')  # 这行代码有Bug
    print('----- try 2 -----')
except ZeroDivisionError:
    # 这里写的是, 出问题后的解决方案
    print('----- except 1 -----')
    src_f = open('1.txt', 'w')
    print('----- except 2 -----')
​
​
# 场景3: 捕获多个异常.
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    # src_f = open('1.txt', 'r')  # 这行代码有Bug
    print(age)
    print(10 // 0)                # 这行代码有Bug
    print('----- try 2 -----')
except (ZeroDivisionError, FileNotFoundError, NameError):
    # 这里写的是, 出问题后的解决方案
    print('哎呀, 程序出错了!')
​
# 场景4: 捕获所有的异常, 因为Python中的异常类型太多了, 我们不可能逐一编写(除非业务固定, 出的问题也固定), 一般会直接写: Exception
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    src_f = open('1.txt', 'r')  # 这行代码有Bug
    print(age)
    print(10 // 0)                # 这行代码有Bug
    print('----- try 2 -----')
except Exception:           # Exception是所有异常的父类, 即: 它代表所有的异常.
    # 这里写的是, 出问题后的解决方案
    print('哎呀, 程序出错了!')
​
# 场景5: 打印异常的信息.
try:
    # 这里写的是: 可能出问题的代码
    print('----- try 1 -----')
    # src_f = open('1.txt', 'r')  # 这行代码有Bug
    # print(age)
    print(10 // 0)                # 这行代码有Bug
    print('----- try 2 -----')
except Exception as e:           # Exception是所有异常的父类, 即: 它代表所有的异常.
    # 这里写的是, 出问题后的解决方案
    # print('哎呀, 程序出错了!')
    print(f"程序出错了, 原因是: {e}")
​
​
print('看看我执行了吗!')

捕获异常完整写法

格式

try:
    里边写可能出问题的代码
except [Exception as e]:                          # 这里的[]表示 可选
    如果出问题了, 这里写的是 处理方式
else:
    如果try中的内容无问题, 则会执行这里.
finally:
    无论try中是否有问题, 都会执行这里的内容.

执行流程

  1. 先执行try中的内容, 看有无问题.

  2. 有问题, 则会立即跳转到 except语句中 执行.

  3. 无问题, 则try中内容执行完毕后, 会跳转到else中执行.

  4. 无论是否有问题, 最终都会执行finally中的内容.

  5. 大白话总结:程序有问题: try => except => finally程序无问题: try => else => finally

演示

# 需求1: 演示 try.except完整格式代码.
try:
    print('----- try 1 -----')
    # print(10 // 0)
    print(10 // 2)
    print('----- try 2 -----')
except Exception as e:
    print(f'程序出问题了, 原因是: {e}')
else:
    print('很开心, 程序没有Bug, 我是else!')
finally:
    print('你们都在说什么, 无论你们执不执行, 我都会执行, 我是finally!')
print('-' * 30)
​
​
# 需求2: 加入异常处理后的, 文件备份的代码.
src_f = open('data/3.jpg', 'rb')
dest_f = open('data/4.jpg', 'wb')
while True:
    data = src_f.read(8192)
    if not data:
        break
    dest_f.write(data)
src_f.close()
dest_f.close()
​
# 标记变量.
flag = False        # False => 文件对象创建失败.  True => 文件对象创建成功.
try:
    # 可能出问题的代码
    src_f = open('data/1.jpg', 'rb')
    dest_f = open('d ata/4.jpg', 'wb')
    flag = True     # 说明 文件对象创建成功.
except Exception as e:
    # 出问题后的解决方案
    print(f'程序出错了, 原因是: {e}')
else:
    # try中代码无问题, 则会执行这里.
    while True:
        data = src_f.read(8192)
        if not data:
            break
        dest_f.write(data)
finally:
    # 无论try中是否有问题, 最终都会走这里, 一般用于: 释放资源.
    if flag:
        src_f.close()
        dest_f.close()
        print('文件对象已关闭!')
    print('程序执行结束了!')

异常传递

概述

异常是具有传递性的, 如果在某个函数内部有Bug, 且该函数没有处理, 则会传给该函数的调用者来处理.依次类推, 逐级传递, 直至传到main函数中, 如果还不处理, 程序就会自动处理. 即: 先打印异常的类型, 描述信息, 位置到控制台上, 并终止程序的运行.

细节

  1. 如果为了保证所有的异常都被处理了, 我们可以在main函数中对异常做处理.

  2. 建议异常越早处理越好, 在哪里发生, 就在哪里处理.

演示

# 需求: 定义函数fun01(), 里边有Bug.  然后由fun02()函数调用fun01()函数, 且在main函数中调用 fun02()函数, 观察会出现什么情况.
# 1. 定义fun01()函数
def fun01():
    print('--- fun01函数 start ---')
    # 情况4: 在fun01函数中, 处理异常.
    try:
        # 有Bug
        print(10 // 0)
    except:
        pass
    print('--- fun01函数 end ---')
​
# 2. 定义fun02()函数, 调用fun01()函数
def fun02():
    print('--- fun02函数 start ---')
    # 情况3: 在 fun02函数中, 处理异常.
    # 调用fun01()函数
    fun01()
    try:
        fun01()
    except:
        pass
    print('--- fun02函数 end ---')
​
# 3. 在main函数中, 测试上述的内容.
if __name__ == '__main__':
    # 情况1: 直接调用 fun02()函数, 看看结果是啥.
    fun02()
​
    # 情况2: 在main中处理异常, 看看结果是啥.
    try:
        # 可能出问题的代码
        fun02()
    except:
        # 出现问题后的解决方案
        pass
​
    # 情况3: 在fun02()函数中, 处理异常, 看看结果是啥.
    fun02()
​
    # 情况4: 在fun01()函数中, 处理异常, 看看结果是啥.
    fun02()
​
    print('看看我执行了吗!')

模块

内置模块介绍

概述

Python中的, 模块 = 1个Python文件 = .py文件.模块中可以写 函数, 类, 变量, 测试代码...

导入模块的方式

  1. import 模块名A. 可以导入 模块下 所有的功能(函数)B. 必须通过 模块名.功能名() 的方式来调用.

  2. import 模块名 as 别名A. 可以导入 模块下 所有的功能(函数)B. 必须通过 别名.功能名() 的方式来调用.

  3. from 模块名 import 功能名A. 只能导入 模块下 指定的功能(函数)B. 可以通过 功能名() 的方式 来直接调用.

  4. from 模块名 import 功能名 as 别名A. 只能导入 模块下 指定的功能(函数)B. 可以通过 别名() 的方式 来直接调用.

  5. from 模块名 import *A. 可以导入 模块下 所有的功能(函数)B. 可以通过 功能名() 的方式 来直接调用.

演示

# 此处以 time模块下的 time()函数, sleep()函数举例.
​
# 演示: 1. import 模块名
import time
​
print(time.time())  # 时间戳, 打印当前时间的秒值, 即: 从时间原点(1970年1月1日 08:00:00) 到 当前时间的 秒值.
print('start')
time.sleep(3)       # 休眠 3 秒
print('end')
​
​
# 演示: 2. import 模块名 as 别名
import time as t
​
print(t.time())  # 时间戳
print('start')
t.sleep(3)       # 休眠 3 秒
print(t.localtime())    # 打印当前时间.
print('end')
​
# 演示: 3. from 模块名 import 功能名
from time import time, sleep
​
print(time())  # 时间戳
print('start')
sleep(2)       # 休眠 2 秒
print('end')
# print(localtime())      # 报错, 因为没有导入, 无法直接使用.
​
# 演示: 4. from 模块名 import 功能名 as 别名
from time import time as t, sleep as ai30
​
print(t())  # 时间戳
print('start')
ai30(2)       # 休眠 2 秒
print('end')
# print(localtime())      # 报错, 因为没有导入, 无法直接使用.
​
# 演示: 5. from 模块名 import *
from time import *
​
print(time())  # 时间戳
print('start')
sleep(2)       # 休眠 2 秒
print('end')
​
print(localtime())      # 报错, 因为没有导入, 无法直接使用.

自定义模块演示

my_module1.py

# 自定义模块, 模块名叫: my_module1, 模块名要做到见名知意, 否则别的模块可能无法调用.
# 在当前模块中可以定义功能(函数), 变量, 类....
​
"""扩展: __name__ 属性, 在当前模块中打印的是: __main__, 在调用者中打印的是: 被调用的模块名
即: __name__属性可以避免: 在调用者中 执行被调用者的 测试代码 这种情况.
"""
​
# 功能 = 函数
def fun01():
    print(__name__)     # 当前模块中, 打印的是 '__main__', 调用者中打印的是: (被调用的模块)当前的模块名
    print('--- my_module1 fun01 函数 ---')
​
​
def fun02():
    print(__name__)
    print('--- my_module1 fun02 函数 ---')
​
​
# 在当前模块中, 对上述的功能(函数)做测试.
# 如果这个if判断条件成立, 说明: 是在当前代码中执行如下的测试内容的.
if __name__ == '__main__':
    fun01()
    fun02()

my_module2.py

# 自定义模块, 模块名叫: my_module2, 模块名要做到见名知意, 否则别的模块可能无法调用.
​
"""
__all__属性:
    1. 它只针对于 from 模块名 import * 有效.
    2. 如果不写 all属性, 则 from 模块名 import * 会导入该模块下所有的功能(函数).
    3. 如果写了 all属性, 则 from 模块名 import * 只会导入 all属性写的函数.
    4. 如果1个模块中的函数较多, 且常用的函数都是固定的, 就可以考虑使用 all属性.
"""
​
# 这行代码意思是: from 模块名 import * 的时候, 只会导入 fun01函数.
__all__ = ['fun01']
​
# 功能 = 函数
def fun01():
    print(__name__)     # 当前模块中, 打印的是 '__main__', 调用者中打印的是: (被调用的模块)当前的模块名
    print('--- my_module2 fun01 函数 ---')
​
​
def fun02():
    print(__name__)
    print('--- my_module2 fun02 函数 ---')
​
​
# 在当前模块中, 对上述的功能(函数)做测试.
# 如果这个if判断条件成立, 说明: 是在当前代码中执行如下的测试内容的.
if __name__ == '__main__':
    fun01()
    fun02()

测试.py

# 案例: 演示调用自定义模块的内容.
​
# 1. 导包.
import my_module1 as m1
import my_module2 as m2
​
import my_module1 as m1, my_module2 as m2
​
​
# 2. 调用m1模块的功能
m1.fun01()
m1.fun02()
print('=' * 30)
​
# 3. 调用m2模块的功能.
m2.fun01()
m2.fun02()
​
​
# 一种特殊情况, 同时导入多个模块, 且模块中有重名函数, 则会使用后导入模块的函数.
from my_module1 import fun01
from my_module2 import fun01
​
fun01() # 打印的是 my_module2模块的函数.
​
​
# 演示 __all__属性, 它只针对于 from 模块名 import * 有效.
from my_module2 import *
​
fun01()
fun02() # 报错, 因为 my_module2的 all属性没写该函数名
​
# all属性只针对于: from 模块名 import * 有效.
from my_module2 import fun01, fun02
fun01()
fun02()

概述

包也叫Package, 你看起来它好像是1个文件夹, 只不过多了一个 init.py文件.包中可以有模块, 且包可以像模块一样被导入.

包 => 模块 => 类, 变量, 功能

细节

  1. 大白话翻译, 包 = 文件夹 + init.py

  2. 我们可以把多个功能相似的模块(例如都是操作容器类型的, 或者都是操作文件的), 放到1个包中, 方便我们集中管理.

  3. 包的本质可以看做是模块, 也可以 导入使用.

导包的两种方式

  1. import 包名.模块名A. 只能导入 包下的某个模块中 所有的内容.B. 必须通过 包名.模块名.功能名() 的方式来调用.

  2. from 包名 import 模块名A. 只能导入 包下的指定模块中 所有的内容.B. 可以通过 模块名.功能名() 的方式来调用.

演示

代码

# 需求: 自定义my_package包, 里边有  my_module1 和 my_module2两个模块. 测试: 该包的功能.
​
# # 导包的方式1, 演示.
import my_package.my_module1
# 必须通过 包名.模块名.功能名() 的方式来调用.
# 包名       模块名      功能名(函数名)
my_package.my_module1.fun01()
my_package.my_module1.fun02()
print('-' * 30)
​
# # 导包的方式2, 演示.
from my_package import my_module2
# 可以通过 模块名.功能名() 的方式来调用.
my_module2.fun01()
my_module2.fun02()
print('-' * 30)
​
# 导包的方式3: from ... import *
from my_package import *
​
# mypackage包下的 my_module1模块.
my_module1.fun01()
my_module1.fun02()
print('-' * 30)
# mypackage包下的 my_module2模块.
my_module2.fun01()
my_module2.fun02()

包文件

扩展Debug

概述

它是程序员的神级技能, 可以帮助我们查看程序的执行流程, 排错等...

步骤

  1. 打断点.那里不会点哪里, 一般是第一行(部分系统是第2行)有效代码处.

  2. 如何开启Debug断点调试.在代码编辑区, 右键 => Debug ...

  3. 如何查看调试信息.下左: MainThread, 类似于 栈, 用于显示: 代码执行到哪里了.下中: Variables, 显示变量值变化过程的.下右: Consoles, 显示程序的运行结果的.

  4. 如何进行下一步.F7: 逐过程调试, 一步一步的走, 遇到自定义函数的时候, 会进到函数的内部.F8: 逐行调试, 一行一行的走, 遇到自定义函数的时候, 不会进到函数的内部, 而是当做一行代码来处理.F9: 逐断点调试, 一个断点一个断点的跳, 如果当前断点已经是最后1个, 再次按下F9则会结束调试.

  5. 如何结束调试.场景1: 调试完.场景2: 手动终止.场景3: 在已经是最后1个断点的情况下, 再次按下F9, 则会结束调试.

  6. 如何删除断点.场景1: 再次点击即可.场景2: 选择 break points图标(双点图标).

测试用代码

# 1. 定义fun01()函数
def fun01():
    print('--- fun01函数 start ---')
    print(10 // 2)
    print('--- fun01函数 end ---')
​
# 2. 定义fun02()函数, 调用fun01()函数
def fun02():
    print('--- fun02函数 start ---')
    # 调用fun01()函数
    fun01()
    print('--- fun02函数 end ---')
​
# 3. 在main函数中, 测试上述的内容.
if __name__ == '__main__':
    fun02()
    print('看看我执行了吗!')

  • 17
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值