# 异常

异常是指程序运行的过程中出现了错误

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