跳到主要内容
Cowers://
全部文章
Python

Python 模块与异常处理基础

从模块导入与包结构讲到异常捕获、主动抛出和自定义异常的基础用法。

一、Python 模块

1. 什么是模块?

模块就是一个 .py 文件。

例如有一个文件:

math_utils.py

它里面写了:

def add(a, b):
    return a + b
 
PI = 3.14

那么 math_utils.py 就是一个模块。

作用:

  • 复用代码
  • 拆分项目结构
  • 避免所有代码都写在一个文件里

2. 导入模块的几种方式

方式一:import 模块名

import math
 
print(math.sqrt(16))

使用时要写:

模块名.函数名

例如:

math.sqrt(16)

方式二:from 模块 import 函数/变量

from math import sqrt
 
print(sqrt(16))

这样可以直接用 sqrt,不用写 math.sqrt


方式三:起别名

import numpy as np

常见例子:

import pandas as pd
import numpy as np

也可以给函数起别名:

from math import sqrt as s
 
print(s(25))

方式四:导入全部,不推荐

from math import *

这样会把 math 里的很多函数都导入进来。

不推荐原因:

from math import *

你不知道到底导入了哪些名字,容易和自己的变量名冲突。


3. 自定义模块

假设你有两个文件:

project/
├── main.py
└── tools.py

tools.py

def hello():
    print("hello")

main.py

import tools
 
tools.hello()

或者:

from tools import hello
 
hello()

4. __name__ == "__main__"

这个很重要。

看代码:

def test():
    print("test running")
 
if __name__ == "__main__":
    test()

含义:

  • 当前文件被直接运行时,__name__ 等于 "__main__"
  • 当前文件被别人导入时,__name__ 等于模块名

例如:

if __name__ == "__main__":
    print("这个文件正在被直接运行")

作用:
防止测试代码在模块被导入时自动执行。


5. 包 package

包就是包含 __init__.py 的文件夹。

例如:

my_package/
├── __init__.py
├── a.py
└── b.py

以前 Python 要求文件夹里有 __init__.py 才能被当作包。现在虽然有些情况可以没有,但一般项目里还是会放。

导入方式:

from my_package import a

或者:

from my_package.a import some_function

二、Python 异常

1. 什么是异常?

异常就是程序运行时发生的错误。

例如:

print(10 / 0)

会报错:

ZeroDivisionError

再比如:

lst = [1, 2, 3]
print(lst[10])

会报错:

IndexError

2. 常见异常类型

异常 含义
ZeroDivisionError 除以 0
IndexError 下标越界
KeyError 字典 key 不存在
ValueError 值不合法
TypeError 类型错误
FileNotFoundError 文件不存在
NameError 变量名不存在
AttributeError 对象没有这个属性

例子:

int("abc")

会报:

ValueError

因为 "abc" 不能转成整数。


三、异常处理

1. 基本格式:try-except

try:
    x = int(input("请输入一个数字:"))
    print(10 / x)
except:
    print("程序出错了")

但是不推荐直接写:

except:

因为它会捕获所有错误,不清楚到底哪里错了。


2. 指定异常类型

try:
    x = int(input("请输入一个数字:"))
    print(10 / x)
except ValueError:
    print("输入的不是数字")
except ZeroDivisionError:
    print("不能除以 0")

执行逻辑:

  1. 先执行 try
  2. 如果没有错误,跳过 except
  3. 如果出现错误,就找对应的 except

3. 获取异常信息

try:
    print(10 / 0)
except ZeroDivisionError as e:
    print("错误信息:", e)

输出:

错误信息: division by zero

这里的 e 保存了异常对象。


4. else

try:
    x = int(input("请输入数字:"))
except ValueError:
    print("输入错误")
else:
    print("输入成功:", x)

else 的含义:

try 里面没有发生异常时,才执行 else


5. finally

try:
    f = open("a.txt", "r")
    print(f.read())
except FileNotFoundError:
    print("文件不存在")
finally:
    print("无论是否出错,都会执行")

finally 的含义:

不管有没有异常,最后都会执行

常用于:

  • 关闭文件
  • 释放资源
  • 关闭数据库连接
  • 清理操作

6. 完整结构

try:
    可能出错的代码
except 异常类型:
    出错后的处理
else:
    没有出错时执行
finally:
    无论如何都执行

记忆方式:

try      尝试执行
except   出错处理
else     没错才执行
finally  最后一定执行

四、主动抛出异常:raise

有时不是 Python 自动报错,而是我们自己主动报错。

age = -1
 
if age < 0:
    raise ValueError("年龄不能小于 0")

这会主动抛出:

ValueError: 年龄不能小于 0

适合用在参数检查里。


五、自定义异常

可以自己定义异常类。

class AgeError(Exception):
    pass
 
age = -1
 
if age < 0:
    raise AgeError("年龄不能为负数")

一般自定义异常要继承:

Exception

六、模块和异常结合使用

比如你写一个模块 calc.py

def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能为 0")
    return a / b

然后在 main.py 里使用:

from calc import divide
 
try:
    print(divide(10, 0))
except ZeroDivisionError as e:
    print("出错了:", e)

这就是实际开发里常见的写法:

  • 模块负责功能
  • 异常负责错误处理