6. Python 异常、模块与包

1. 异常

1.1 了解异常

当检测到一个错误时,Python 解释器就无法继续执行,出现一些错误的提示,这就是 “异常”,也就是 Bug。

1.2 异常的捕获方法

捕获异常的作用在于:提前假设某处会出现异常,提前做好准备。当真的出现异常的时候,可以有后续手段。

1.2.1 捕获所有异常

方式1:

try:
	可能发生错误的代码
except:
	如果出现异常执行的代码

【例】尝试以 r 模式打开文件,如果文件不存在,则以 w 方式打开。

try:
    f = open("D:/abc.txt", "r", encoding="utf-8")
except:
    print("出现异常,将以'w'模式打开文件")
    f = open("D:/abc.txt", "w", encoding="utf-8")

方式2(一般用这种):
在 except 后面,加上异常类型 Exception。
【例】

try:
    print(1 / 0)
except Exception as e:
    print(f"出现了{e}异常")#出现了division by zero异常

1.2.2 捕获指定异常

基本语法:

try:
    print(1 / 0)
except ZeroDivisionError as e:
    print(f"出现了{e}异常")#出现了division by zero异常

注意事项
① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
② 一般 try 下方只放一行尝试执行的代码。
③ 如果不知道 except 后面的异常名写什么,可以先不捕获,从控制台看一下。如上面代码中的,可以直接运行 print(1/0),从控制台得到异常名称:
在这里插入图片描述

1.2.3 捕获多个异常

当捕获多个异常时,可以把异常类型的名字统一放在元组中,放到 except 后。

try:
    print(name)
except (ZeroDivisionError, NameError) as e:
    print(f"出现了{e}异常")

输出结果:

出现了name 'name' is not defined异常

1.2.4 异常 else(可选)

else:表示的是如果没有异常要执行的代码,else 部分也可以不写。

try:
	print(1)
except Exception as e:
	print(e)
else:
    print("我是else,是没有异常的时候执行的代码")

输出结果:

1
我是else,是没有异常的时候执行的代码

1.2.5 异常 finally(可选)

finally:表示的是无论是否异常都要执行的代码,例如:关闭文件。finally 部分也可以不写

【例】以r模式打开 aaa.txt 文件,若文件不存在就创建以 w 模式打开的新文件。

try:
    f = open("D:/aaa.txt", "r", encoding="utf-8")
except Exception as e:
    print("aaa.txt不存在,创建以w模式打开的新文件")
    f = open("D:/aaa.txt", "w", encoding="utf-8")
else:
    print("未出现异常")
finally:
    print("不管是否出现异常,都执行finally")
    f.close()

输出结果:

aaa.txt不存在,创建以w模式打开的新文件
不管是否出现异常,都执行finally

1.2.6 细节问题

出现异常时,try 块中,异常后面剩余的语句不会执行。

try:
    print("1111")
    print(1/0)
    print("2222")#不会执行

except Exception as e:
    print("出现异常")

print("程序结束")

输出结果:

1111
出现异常
程序结束

1.2.7 捕获异常的语法总结

try:
	可能要发生异常的语句
except[异常 as 别名]:
	出现异常的准备手段
[else:]
	未出现异常时应做的事情
[final1y:]
	不管出不出现异常都会做的事情

1.3 异常的传递

若 main、func1、func2 有如下调用关系:
在这里插入图片描述

每个函数内部出现异常时,都有两种处理方式:① 自己捕获处理;② 向调用者传递异常。
当函数 func2 中发生异常,并且没有捕获处理这个异常的时候,异常会传递到函数func1;
当 func1 也没有捕获处理这个异常的时候,异常会传递到 main 函数,若 main 函数捕获处理这个异常,异常就得到处理,否则报错。这就是异常的传递性。

def func2():
    print("func2开始执行")
    print(1 / 0)  # 发生异常
    print("func2结束执行")

def func1():
    print("func1开始执行")
    func2()
    print("func1结束执行")

def main():
    try:
        func1()
    except Exception as e:
        print("出现了异常")

main()

输出结果:

func1开始执行
func2开始执行
出现了异常

2. 模块

2.1 模块引入

什么是模块
  模块(Module)是一个 Python 文件,以.py结尾。模块能定义函数、类和变量,也能包含可执行的代码。
.
模块的作用
  Python 中有很多各种不同的模块,每一个模块都可以快速地实现一些功能,比如:实现与时间相关的功能可以使用 time 模块。
  可以认为一个模块就是一个工具包,每一个工具包中都有各种不同的工具,实现各种不同的功能。
  在代码中,可以通过 Ctrl + B 定位到模块对应的 Python 文件或具体的函数、类、变量等。

2.2 模块的导入方式

  模块在使用前需要先导入,模块的导入一般写在代码文件的开头位置。导入的语法如下:

[from 模块名] import [模块||变量|函数|*] [as 别名]

常用的组合形式如:

  • import 模块名
  • from 模块名 import 类、变量、方法等
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名

(1) import 模块名

基本语法:

import 模块名
import 模块名1, 模块名2
模块名.功能名()

【例】导入 time 模块

# 导入时间模块
import time
print("开始")
# 让程序睡眠5秒(阻塞)
time.sleep(5)
print("结束")

(2) from 模块名 import 功能名

基本语法:

from 模块名 import 功能名
功能名()

【例】导入time 模块中的 sleep 方法

#只导入时间模块中的sleep方法
from time import sleep
print("开始")
#让程序睡眠5秒(阻塞)
sleep(5)
print("结束")

(3) from 模块名 import *

基本语法:

from 模块名 import *
功能名()

【例】导入time 模块中所有的方法

#导入时间模块中所有的方法
from time import *
print("开始")
#让程序睡眠5秒(阻塞)
sleep(5)
print("结束")

(4) as 定义别名

基本语法:

# 模块定义别名
import 模块名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名

【例】

# 模块别名
import time as tt
tt.sleep(2)
print('hello')
# 功能别名
from time import sleep as sl
sl(2)
print('hello')

2.3 自定义模块

  Python 中已经实现了很多的模块,不过有时候需要一些个性化的模块,这时就可以通过自定义模块实现,也就是自己制作一个模块。

自定义 my_module 模块:

# test函数在my_module.py文件中
def test(a, b):
    return a + b

使用方式 1:

#想要调用的函数所在的文件名,要符合标识符命名规则
import my_module 
res = my_module.test(1, 2)
print(res)#输出3

使用方式 2:

from my_module import test
res = test(1, 2)
print(res)#输出3

当导入多个模块,且模块内有同名功能时,若调用这个同名功能,调用到的是后面导入模块的功能。

#模块1
def test(a, b):
print(a + b)
#模块2
def test(a, b):
print(a - b)
#导入模块和调用功能
from my_module1 import test#在pycharm中是灰色,表示没用
from my_module2 import test
#模块2的test函数将模块1的test函数覆盖了
#所以,test函数是模块2中的函数
test(1, 1)

2.4 测试模块

当编写完一个模块后,通常要进行测试。如: 在 my_module1.py 中添加测试代码test(1, 1),从而右键运行 my_module1.py 时,能够测试 test 函数。

# my_module1.py
def test(a, b):
	print(a + b)
test(1,1)

此时,若在其他文件中直接 import my_module1,就会直接执行 test(1,1),输出 3。

import my_module1 #输出3

这是不合理的,但又不想删除 my_module1.py 中的测试代码 test(1,1)。这时就可以把测试代码写入if __name__ == '__main__':中。

def test(a, b):
    print(a + b)

if __name__ == '__main__':
    test(1, 2)

这样,直接右键执行 my_module1.py 进行测试时,会输出 test(1,1) 的执行结果; 而 import my_module1 时,就不会再执行 test(1,1)。

2.5 __all__ 变量

__all__ 变量可以控制 import * 的时候哪些功能可以被导入。(all 的两侧各有 2 个下划线 “_”)
如果一个模块文件中有__all__ 变量,当使用 from xxx import * 导入时,只能导入这个列表中的元素。
在这里插入图片描述
__all__ 变量只能限制 from my_module1 import *,还是可以通过 from my_module1 import test_B 导入 test_B 函数的。而且 import my_module1 也不受限制,可以通过 my_module1.test_B() 调用 test_B 函数。

3. Python 包

3.1 自定义包

基于 Python 模块,就可以在编写代码时,导入外部代码来丰富功能。
但是,若 Python 的模块太多,就可能造成混乱,这时就可以用包来管理。

什么是Python包
包就是一个文件夹,其中包含一个__init__.py 文件,也可以包含多个模块文件。包的本质依然是模块。
一个文件夹中,若有__init__.py 文件,就是包;否则就是普通文件夹。
在这里插入图片描述
自定义 Python 包
① 新建包 my_package
② 新建包内模块:my_module1 和 my_module2
③ 在模块中写入代码
Pycharm 中的具体操作:[New]➡[Python Package]➡输入包名➡[OK]➡新建功能模块

注意:新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为。

在这里插入图片描述

导入自定义的包

方式 1:

# test.py文件
import my_package.my_module1
import my_package.my_module2
my_package.my_module1.info_print1()#my_module1
my_package.my_module2.info_print2()#my_module2

方式 2:

# test.py文件
from my_package import my_module1
from my_package import my_module2
my_module1.info_print1()#my_module1
my_module2.info_print2()#my_module2

方式3:

# test.py文件
from my_package.my_module1 import info_print1
from my_package.my_module2 import info_print2
info_print1()
info_print2()

__all__ 控制导入模块
__init__.py 文件中添加__all__ = [],可以指定允许导入的模块。
__all__ 针对的是 “from… import*” 这种方式,对其他指定确切导入模块或功能的方式无效。

# __init__.py文件
__all__ = ["my_module1"]
# test.py文件
from my_package import *
my_module1.info_print1()
# my_module2.info_print2()#不能用

3.2 安装第三方包

什么是第三方包
  包可以包含一堆的 Python 模块,而每个模块又内含许多的功能。所以可以认为:一个包,就是一堆同类型功能的集合体。
  在 Python 中,有许多第三方包(非Python官方),可以极大的帮助我们提高开发效率,如:

  • 科学计算中常用的:numpy包
  • 数据分析中常用的:pandas包
  • 大数据计算中常用的:pyspark、apache-flink包
  • 图形可视化常用的:matplotlib、pyecharts
  • 人工智能常用的:tensorflow 等

  这些第三方的包,极大的丰富了 Python 的生态,提高了开发效率。
  但是由于是第三方,所以 Python 没有内置,所以我们需要安装它们才可以导入使用。

如何安装第三方包

方式 1:在命令提示符内:
pip install 包名称(速度慢)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称(速度快,推荐)
检验是否安装成功:
在这里插入图片描述

方式 2:在 PyCharm 中:

(1)点击PyCharm 右下角解释器设置
在这里插入图片描述
(2)(下面展示的是一些已经安装过的包)点击加号。
在这里插入图片描述
(3)搜索要下载的包,以 tensorflow 为例,用清华源,点击安装。稍等一下就安装好了。
在这里插入图片描述
(4)验证是否安装成功
在(2)中的列表内就能看到已经安装过的包。

【例】创建一个自定义包,名称为:my_utils,在包内提供 2 个模块:

  • str_util.py(字符串相关工具,内含:)
    str_reverse(s),接受传入字符串,将字符串反转返回。
    substr(s, x, y),按照下标 x 和 y ,对字符串进行切片。
  • file_util.py(文件处理相关工具,内含:)
    print_file_info(file_name),接收传入文件的路径,打印文件的全部内容,如文件不存在则捕获异常,输出提示信息,通过 finally 关闭文件对象。
    append_to_file(file_name, data),接收文件路径以及传入数据,将数据追加写入到文件中。

构建出包后,尝试着用一用自己编写的工具包。

# str_util.py
def str_reverse(s):
    return s[::-1]

def substr(s,x,y):
    return s[:x], s[x:y], s[y:]
# file_util.py
def print_file_info(file_name):
    f = None
    try:
        f = open(file_name, "r", encoding="utf-8")
        for line in f:
            print(line)
    except Exception as e:
        print("文件不存在")
    finally:
        if f:#变量赋值不成功,没有默认值?
            f.close()

def append_to_file(file_name,data):
    f = open(file_name, "a", encoding="utf-8")
    f.write(data)
    f.close()
# test.py
from my_utils import str_util, file_util
print(str_util.str_reverse("hello"))
str1, str2, str3 = str_util.substr("0123456789", 3, 7)
print(str1, str2, str3)
print("====================================")
file_util.print_file_info("D:/abc.txt")
file_util.append_to_file("D:/abc.txt", "新添加的内容")
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值