# 异常
异常是指程序运行的过程中出现了错误
bug 就是指异常,历史上因为小虫子导致计算机失灵,所以延续至今,bug 就代表软件出现错误
# 异常的捕获
异常处理(捕获异常):针对可能出现的异常,提前做好准备,当真的出现异常时,可以有后续处置,以免其导致程序无法正常运行
# 捕获常规异常
语法:
try: | |
尝试执行的代码 | |
except: | |
若出现异常,将会执行本段代码 |
例如:
# 尝试以 'r' 模式打开文件,如果文件不存在,则以 'w' 方式打开 | |
try: | |
f = open('linux.txt', 'r') | |
except: | |
f = open('linux.txt', 'w') |
# 捕获指定异常
try: | |
尝试执行的代码 | |
except ErrorType as e: | |
若出现类型为 ErrorType 的异常,将会执行本段代码 |
其中,ErrorType 是指要捕获的异常类型
注意:如果 “尝试执行的代码” 的异常类型和要捕获的异常类型不一致,则无法捕获异常
常见的异常类型如下表所示:
类名 | 描述 |
---|---|
SyntaxError |
发生语法错误时引发 |
FileNotFoundError |
未找到指定文件或目录时引发 |
NameError |
找不到指定名称的变量时引发 |
ZeroDivisionError |
除数为 0 时的异常 |
IndexError |
当使用超出列表范围的索引时引发 |
KeyError |
当使用映射不存在的键时引发 |
AttributeError |
当尝试访问未知对象属性时引发 |
TypeError |
当试图在使用 a 类型的场合使用 b 类型时引发 |
例如:
try: | |
print(name) | |
except NameError as e: | |
print('未定义 name 变量') |
# 捕获多个异常
当需要捕获多个异常时,可以把要捕获的异常类型的名字,放到 except 后,并使用元组的方式进行书写
例如:
捕获多个异常(但不输出异常的具体描述):
try: | |
print(1 / 0) | |
except (NameError, ZeroDivisionError): | |
print('错误...') |
捕获多个异常并输出异常的具体信息:
try: | |
print(num) | |
except (NameError, ZeroDivisionError) as e: | |
print(e) |
# 捕获所有异常
try: | |
尝试执行的代码 | |
except Exception as e: | |
若出现异常,将会执行本段代码 |
注意: except:
与 except Exception as e:
这两种方式都可以捕获全部的异常
# 异常 else
else
表示没有异常时要执行的代码
try: | |
尝试执行的代码 | |
except Exception as e: | |
若出现异常,将会执行本段代码 | |
else: | |
若没有出现异常,将会执行本段代码 |
# 异常 finally
finally
表示无论是否异常都要执行的代码,例如关闭文件
try: | |
尝试执行的代码 | |
except Exception as e: | |
若出现异常,将会执行本段代码 | |
else: | |
若没有出现异常,将会执行本段代码 | |
finally: | |
无论是否出现异常,都会执行本段代码 |
# 异常的传递
异常具有传递性:
-
当函数 / 方法执行出现异常,会将异常传递给函数 / 方法的调用一方
-
如果传递到主程序,仍然没有异常处理,程序才会被终止
利用异常具有传递性的特点,当我们想要保证程序不会因为异常崩溃的时候,就可以在 main
函数中设置异常捕获,由于无论在整个程序哪里发生异常,最终都会传递到 main
函数中,这样就可以确保所有的异常都会被捕获
# 模块
Python 模块(Module),是一个 Python 文件,以 .py
为后缀名
模块能定义函数、类和变量,模块里也能包含可执行的代码
可以认为一个模块就是一个工具包,每一个工具包中都有各种不同的工具供我们使用,以实现各种不同的功能
# 导入模块
在使用模块之前,需要先将模块导入 Python 程序
常用的导入模块方式:
import module_name | |
from module_name import class_name, var_name, func_name | |
from module_name import * | |
import module_name as nick_name | |
from module_name import func_name as nick_name |
其中:
- module_name 表示模块
- class_name 表示模块内的类
- var_name 表示模块内的变量
- func_name 表示模块内的函数
- nick_name 表示为模块自定义的别名
注意:导入模块时,module_name 不需要包含 .py
后缀
# import module_name
使用 import
导入模块后,可以通过 '.'
来使用模块中的函数或类
import module_name | |
module_name.func_name() | |
module_name.class_name | |
module_name.var_name |
# from module_name import func_name
使用 from … import …
方式导入之后,无需添加前缀,直接调用即可
from module_name import func_name | |
func_name() |
注意,利用 from
把内容从模块中导入后,会导致相同名称的内容被覆盖,也就是说,不同模块的命名空间会在此处重叠
# from module_name import *
导入模块全部内容
from module_name import * | |
func_name() | |
class_name | |
var_name |
# as nick_name
# 模块定义别名 | |
import module_name as nick_name | |
# 功能定义别名 | |
from module_name import func_name as func_nick_name |
# 自定义模块
每个 Python 文件都可以作为一个模块,模块的名字就是文件的名字
因此,自定义模块只需在 Python 代码文件中正常写代码即可,通过 import、from 关键字导入(与导入 Python 内置模块一样)即可使用。但是需要注意,自定义模块名必须要符合标识符命名规则
# __main__ 变量
if __main__ == “__main__”
语句的作用:只有当含有该语句的 Python 程序是被直接 run 时,才会进入 if
内部。如果是被导入的,则无法进入 if
该功能常用于测试模块(即,希望某些代码在测试时运行、而在被导入时不运行)
例如:
def test(a, b): | |
print(a + b) | |
# 只在当前文件中调用该函数,其他导入的文件内均不执行 test 函数调用 | |
if __name__ == '__main__': | |
test (1, 1) |
如果不加 if __name__ == "__main__"
语句:无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行 test
函数的调用
# __all__ 变量
如果一个模块文件中有 __all__
变量(该变量为列表对象),在使用 from xxx import *
导入该模块时,只能导入 __all__
列表中的元素
因此, __all__
变量可以控制 import *
导入模块时的导入内容
注意: __all__
变量 仅影响 from ... import *
这一导入方式
例如,自定义如下模块:
__all__ = ['Test_A'] | |
def Test_A(): | |
xxx | |
def Test_B(): | |
xxx |
通过 from ... import *
导入该模块后,只能使用 Test_A
函数,而不能使用 Test_B
函数
# 包
如果 Python 模块太多,可以通过 Python 包(Package)来管理
当我们的模块文件非常多时,包可以帮助我们管理这些模块,包的作用就是包含多个模块,但包的本质依然是模块
-
从物理上看:包就是一个文件夹,在该文件夹下包含了一个
__init__.py
文件,该文件夹可包含多个模块文件 -
从逻辑上看:包的本质依然是模块
# 自定义包
基本步骤:
- 新建 Python Package
- 新建 Python 模块
在 Pycharm 中,点击 new --> Python Package
新建包后,包内部会自动创建 __init__.py
文件,这个文件控制着包的导入行为
# 导入包
# import xxx
# 导入所有模块
import package_name | |
package_name.module_name.func_name() |
# 导入指定模块
import package_name.module_name | |
package_name.module_name.func_name() |
其中:
- package_name 表示 Python Package 名称
- module_name 表示 Python Package 中的模块名称
- func_name 表示模块中的函数名称
# from xxx import
# 导入所有模块
from package_name import * | |
module_name.func_name() |
注意:必须在 __init__.py
文件中添加 __all__
变量,用于控制 from package_name import *
导入的模块列表(类似于模块文件中的 __all__
变量)
# 导入指定模块
from package_name import module_name | |
module_name.func_name() |
# 导入指定模块中的指定函数
from package_name.module_name import func_name | |
func_name() |
# 第三方包
在 Python 程序的生态中,有许多非常多的第三方包(非 Python 官方),可以极大的帮助我们提高开发效率,如:
- 科学计算:numpy
- 数据分析:pandas
- 大数据计算:pyspark、apache-flink
- 图形可视化:matplotlib、pyecharts
- 人工智能:tensorflow
注意,Python 没有内置这些第三方包,需要安装它们才可以导入使用
可通过 Python 内置的 pip 安装指定的第三方包
即,在命令行中输入:
pip install package_name |
pip 是连接外网进行下载,若下载速度相对较慢,可考虑通过国内的镜像源下载
例如:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package_name |