Python3入门指南Python语言的特点和实际应用Python3环境搭建配置VSCode进行Python开发Python基础语法Python变量与数据类型Python数据类型转换Python解释器使用Python注释使用Python运算符Python数字类型Python字符串操作Python列表操作Python元组使用Python字典使用Python集合使用Python条件控制详解Python循环语句详解Python编程入门实践Python推导式详解Python迭代器和生成器Python with语句详解Python函数详解Python lambda(匿名函数)Python装饰器Python数据结构Python模块和包使用Python中__name__和__main__的用法Python输入输出:从基础到文件操作Python文件操作Python OS模块使用Python错误和异常处理Python面向对象编程Python命名空间和作用域Python虚拟环境:venv详细教程Python类型注解Python标准库常用模块Python正则表达式Python CGI编程Python MySQL(mysql-connector驱动)Python MySQL(PyMySQL驱动)Python网络编程Python发送邮件Python多线程编程Python XML解析Python JSON解析Python日期和时间处理Python操作MongoDBPython urllib库使用Python uWSGI 安装与配置Python pip包管理工具Python operator模块Python math模块Python requests模块HTTP请求Python random模块Python OpenAI库Python AI绘画制作Python statistics模块Python hashlib模块:哈希加密Python量化交易Python pyecharts数据可视化Python Selenium网页自动化Python BeautifulSoup网页数据提取Python Scrapy爬虫框架Python Markdown转HTMLPython sys模块Python Pickle模块:数据存储Python subprocess模块Python queue队列模块Python StringIO内存文件操作Python logging日志记录Python datetime日期时间处理Python re正则表达式Python csv表格数据处理Python threading 多线程编程Python asyncio 异步编程Python PyQt 图形界面开发Python 应用方向和常用库框架

Python错误和异常处理

在学习Python编程时,遇到错误信息是很常见的情况。Python会通过错误提示来告诉我们程序哪里出了问题。了解这些错误信息并学会处理异常,是成为合格程序员的重要一步。


Python中的两种错误

Python主要有两种错误类型:语法错误和异常。

语法错误

语法错误是初学者最容易遇到的错误。这种错误发生在代码编写阶段,通常是因为没有遵守Python的语法规则。

比如下面这个例子:

# 错误的写法
while True print('Hello world')

运行这段代码会显示:

SyntaxError: invalid syntax

错误信息会指出问题所在的位置。在这个例子中,print前面缺少了冒号,正确的写法应该是:

# 正确的写法
while True:
    print('Hello world')

异常

即使代码语法完全正确,运行时也可能出现问题,这种情况叫做异常。

常见的异常例子:

# 除以零错误
result = 10 * (1/0)  # ZeroDivisionError: division by zero

# 使用未定义的变量
value = 4 + spam * 3  # NameError: name 'spam' is not defined

# 类型不匹配
text = '2' + 2  # TypeError: can only concatenate str (not "int") to str

每种异常都有特定的类型,比如ZeroDivisionError、NameError、TypeError等。


异常处理的基本方法

使用try-except

我们可以使用try-except语句来捕获和处理异常。

# 处理用户输入错误
while True:
    try:
        number = int(input("请输入一个数字: "))
        break  # 如果输入正确,跳出循环
    except ValueError:
        print("输入的不是有效数字,请重新输入!")

print(f"你输入的数字是: {number}")

处理多种异常

一个try语句可以包含多个except子句,用于处理不同类型的异常。

try:
    # 尝试打开文件并读取内容
    with open('data.txt', 'r') as file:
        content = file.read()
        number = int(content.strip())
        
except FileNotFoundError:
    print("文件不存在")
except ValueError:
    print("文件内容不是有效的数字")
except Exception as e:
    print(f"发生了未知错误: {e}")

使用else子句

else子句中的代码只在try块没有发生异常时执行。

try:
    number = int(input("请输入数字: "))
except ValueError:
    print("输入的不是数字")
else:
    # 只有在没有异常时才执行
    result = number * 2
    print(f"两倍结果是: {result}")

使用finally子句

finally子句中的代码无论是否发生异常都会执行。

try:
    file = open('example.txt', 'r')
    content = file.read()
    number = int(content)
except (FileNotFoundError, ValueError) as e:
    print(f"错误: {e}")
finally:
    # 无论是否出错,都要关闭文件
    file.close()
    print("文件已关闭")


实际应用示例

示例1:安全的数字输入

def get_positive_number():
    """获取用户输入的正数"""
    while True:
        try:
            number = float(input("请输入一个正数: "))
            if number <= 0:
                print("请输入大于0的数字")
                continue
            return number
        except ValueError:
            print("请输入有效的数字")
        except KeyboardInterrupt:
            print("\n程序被用户中断")
            return None

# 使用示例
num = get_positive_number()
if num is not None:
    print(f"你输入的数字是: {num}")

示例2:文件操作异常处理

def read_config_file(filename):
    """安全地读取配置文件"""
    config = {}
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            for line_num, line in enumerate(file, 1):
                line = line.strip()
                if line and not line.startswith('#'):  # 跳过空行和注释
                    try:
                        key, value = line.split('=', 1)
                        config[key.strip()] = value.strip()
                    except ValueError:
                        print(f"第{line_num}行格式错误: {line}")
                        
    except FileNotFoundError:
        print(f"配置文件 {filename} 不存在")
    except PermissionError:
        print(f"没有权限读取文件 {filename}")
    except UnicodeDecodeError:
        print(f"文件编码错误,请使用UTF-8编码")
    
    return config

# 使用示例
config = read_config_file('app.config')
print("配置内容:", config)

示例3:网络请求异常处理

import requests

def safe_download(url, timeout=10):
    """安全地下载网页内容"""
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()  # 如果状态码不是200,抛出异常
        return response.text
        
    except requests.exceptions.Timeout:
        print("请求超时,请检查网络连接")
    except requests.exceptions.ConnectionError:
        print("网络连接错误,请检查URL是否正确")
    except requests.exceptions.HTTPError as e:
        print(f"HTTP错误: {e}")
    except Exception as e:
        print(f"未知错误: {e}")
    
    return None

# 使用示例
content = safe_download("https://fly63.com")
if content:
    print("下载成功,内容长度:", len(content))


主动抛出异常

我们可以使用raise语句主动抛出异常。

基本用法

def validate_age(age):
    """验证年龄是否有效"""
    if not isinstance(age, int):
        raise TypeError("年龄必须是整数")
    if age < 0:
        raise ValueError("年龄不能为负数")
    if age > 150:
        raise ValueError("年龄不能超过150岁")
    return True

# 测试
try:
    validate_age(-5)
except ValueError as e:
    print(f"验证失败: {e}")

在特定条件下抛出异常

def process_order(amount, inventory):
    """处理订单"""
    if amount <= 0:
        raise ValueError("订单数量必须大于0")
    if amount > inventory:
        raise Exception(f"库存不足,当前库存: {inventory}")
    
    print(f"订单处理成功,数量: {amount}")
    return True

# 使用示例
try:
    process_order(10, 5)  # 库存只有5,要买10个
except Exception as e:
    print(f"订单处理失败: {e}")


自定义异常

我们可以创建自己的异常类,让错误处理更加精确。

class BankAccountError(Exception):
    """银行账户相关异常的基类"""
    pass

class InsufficientFundsError(BankAccountError):
    """余额不足异常"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        super().__init__(f"余额不足。当前余额: {balance}, 需要: {amount}")

class InvalidAmountError(BankAccountError):
    """无效金额异常"""
    pass

class BankAccount:
    def __init__(self, initial_balance=0):
        self.balance = initial_balance
    
    def withdraw(self, amount):
        if amount <= 0:
            raise InvalidAmountError("取款金额必须大于0")
        if amount > self.balance:
            raise InsufficientFundsError(self.balance, amount)
        
        self.balance -= amount
        print(f"取款成功: {amount}, 当前余额: {self.balance}")
        return amount

# 使用示例
account = BankAccount(1000)

try:
    account.withdraw(1500)  # 尝试取出1500,但余额只有1000
except InsufficientFundsError as e:
    print(f"取款失败: {e}")
except BankAccountError as e:
    print(f"账户操作失败: {e}")


断言(assert)的使用

assert语句用于在代码中检查条件是否满足,如果不满足就抛出AssertionError。

def calculate_average(numbers):
    """计算数字列表的平均值"""
    assert isinstance(numbers, list), "输入必须是列表"
    assert len(numbers) > 0, "列表不能为空"
    assert all(isinstance(x, (int, float)) for x in numbers), "列表元素必须是数字"
    
    return sum(numbers) / len(numbers)

# 测试
try:
    result = calculate_average([])  # 空列表
except AssertionError as e:
    print(f"断言错误: {e}")


使用with语句自动清理资源

with语句可以确保资源被正确释放,即使发生异常也不例外。

# 自动关闭文件
with open('data.txt', 'r') as file:
    content = file.read()
    # 即使这里发生异常,文件也会被正确关闭
    numbers = [int(x) for x in content.split()]

# 文件已经自动关闭,不需要手动调用file.close()
print("处理完成,文件已自动关闭")


调试技巧

获取详细的错误信息

import traceback

def debug_function():
    try:
        # 可能出错的代码
        result = 10 / 0
    except Exception as e:
        print("错误类型:", type(e).__name__)
        print("错误信息:", str(e))
        print("详细的错误跟踪:")
        traceback.print_exc()

debug_function()

记录错误日志

import logging

# 配置日志
logging.basicConfig(
    filename='app.log',
    level=logging.ERROR,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def safe_operation():
    try:
        # 业务逻辑
        risky_operation()
    except Exception as e:
        logging.error(f"操作失败: {e}", exc_info=True)
        print("操作失败,详情请查看日志文件")

safe_operation()


最佳实践建议

  1. 具体处理异常:不要简单地使用except:,应该捕获具体的异常类型

  2. 提供有用的错误信息:让用户知道发生了什么以及如何修复

  3. 不要过度使用异常:正常的程序流程不应该依赖异常处理

  4. 记录异常:在生产环境中记录异常信息以便调试

  5. 保持简洁:异常处理代码应该清晰易懂

# 好的做法
try:
    value = int(user_input)
except ValueError:
    print("请输入有效的整数")

# 不好的做法
try:
    value = int(user_input)
except:
    print("出错了")  # 信息不具体,而且会捕获所有异常

掌握异常处理技巧,能够让你的程序更加健壮和用户友好。记住,好的程序不仅要能正确处理正常情况,还要能优雅地处理异常情况。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/course/36_2103

目录选择