当前位置:首页>python>Python异常处理最容易踩的5个坑,第3个连老手都翻车

Python异常处理最容易踩的5个坑,第3个连老手都翻车

  • 2026-03-27 07:16:45
Python异常处理最容易踩的5个坑,第3个连老手都翻车

详解try/except避坑指南,看完再也不怕程序崩溃


你正在开发一个扫雷游戏,玩家点击格子时,你信心满满地写下了这样的代码:

defclick_cell(x, y):
    board[x][y].revealed = True
if board[x][y].has_mine:
        game_over()

然后测试的时候,玩家win+Tab切出去回个消息,回来点击格子——程序原地爆炸

你看着控制台满屏的IndexError,陷入了沉思:明明本地测试得好好的,怎么换个环境就崩了

恭喜你,你踩到了Python异常处理的第一个坑

作为一个写代码经常翻车的老玩家,今天我把异常处理中最常见的5个坑全部整理出来了
第3个坑连工作好几年的老手都会翻车,建议先收藏再看


第一个坑:裸奔的try-except - 你的程序正在"裸泳"

场景重现:猜数字游戏的诡异崩溃

小甲鱼写了这样一个猜数字游戏:

import random

defguess_number():
    target = random.randint(1100)
print(f"我想了一个1-100之间的数字,你猜是几?")

whileTrue:
try:
            guess = int(input("请输入你的猜测: "))
if guess == target:
print("恭喜你,猜对了!")
break
elif guess < target:
print("太小了!")
else:
print("太大了!")
except:
print("请输入有效的数字!")

看起来很完美对不对
用户输入非数字时,会打印"请输入有效的数字
"

**但实际上,这个程序有个致命问题——它在偷偷吞掉所有异常
**

当程序出现任何其他问题时,比如你后续加了一个计分功能:

defadd_score(points):
    score = get_score()  # 假设这个函数有问题
    score += points

如果get_score()抛出AttributeError,这个异常会被上面的裸except吞掉,用户只会看到"请输入有效的数字
",而实际上问题完全无关输入

问题分析

裸奔的except(即except:不指定异常类型)相当于给程序穿了一件透明雨衣——看起来在保护它,其实完全没用
它会捕获所有异常,包括KeyboardInterrupt(用户按Ctrl+C)、SystemExit(程序退出),甚至MemoryError(内存不足)

解决方案

永远指定具体的异常类型

try:
    guess = int(input("请输入你的猜测: "))
except ValueError:
print("请输入有效的数字!")
except KeyboardInterrupt:
print("\n游戏被中断,再见!")
break

完整代码示例

import random

defguess_number():
    target = random.randint(1100)
    attempts = 0
print("=" * 40)
print("🎮 猜数字游戏 - 异常处理教学版")
print("我想了一个1-100之间的数字,你猜是几?")
print("输入 'q' 退出游戏")
print("=" * 40)

whileTrue:
try:
            user_input = input("请输入你的猜测: ")

# 处理退出
if user_input.lower() == 'q':
print(f"游戏结束!你总共猜了{attempts}次")
break

# 只捕获ValueError - 输入解析错误
            guess = int(user_input)
            attempts += 1

if guess == target:
print(f"🎉 恭喜你,猜对了!你总共用了{attempts}次机会")
break
elif guess < target:
print("📉 太小了!继续猜")
else:
print("📈 太大了!继续猜")

except ValueError:
print("❌ 输入错误!请输入一个整数(或输入'q'退出)")
except KeyboardInterrupt:
print("\n👋 游戏被中断,再见!")
break

if __name__ == "__main__":
    guess_number()

避坑要点:只捕获你知道的、能够处理的异常类型
不要用裸except,它会让你的调试变成噩梦


第二个坑:except Exception - 你在用渔网捞鱼

场景重现:计算器的隐藏炸弹

继续说小甲鱼的计算器项目
这次他学聪明了,不用裸奔的except,而是用了Exception

defcalculator():
whileTrue:
try:
            expression = input("请输入计算式 (如 2+3): ")
            result = eval(expression)
print(f"结果是: {result}")
except Exception as e:
print(f"计算出错: {e}")

看起来很棒,还能打印错误信息帮助用户

但某天,用户输入了import os; os.system('rm -rf /')……

虽然eval本身就很危险,但这里我们要说的是另一个问题:你在用渔网捞鱼的时候,把大鲨鱼也捞进来了

问题分析

Exception是所有非系统退出的异常的基类
except Exception相当于说"我想捕获所有可能出错的情况"——但这通常是懒惰的做法

问题在于:

  1. 1. 你无法区分不同类型的错误
  2. 2. 某些异常本不应该被捕获(比如StopIteration在生成器中使用时)
  3. 3. 代码的可读性极差,后续维护的人不知道你会处理什么

解决方案

按具体异常类型分层捕获

defsafe_calculator():
whileTrue:
try:
            expression = input("请输入计算式 (如 2+3): ")
            result = eval(expression)
print(f"结果是: {result}")
except ZeroDivisionError:
print("❌ 除数不能为零!")
except SyntaxError:
print("❌ 表达式语法错误,请检查输入格式")
except (TypeError, NameError) as e:
print(f"❌ 计算错误: {str(e)}")
except KeyboardInterrupt:
print("\n👋 计算器已退出")
break

完整代码示例

defcalculator():
"""带详细异常处理的计算器"""
print("=" * 50)
print("🧮 智能计算器 - 异常处理进阶版")
print("支持 + - * / ** % // 操作")
print("输入 'help' 查看帮助,'quit' 退出")
print("=" * 50)

whileTrue:
try:
            user_input = input("\n请输入计算式: ").strip()

if user_input.lower() in ('quit''q''exit'):
print("👋 计算器已退出,感谢使用!")
break

if user_input.lower() == 'help':
                print_help()
continue

# 检查输入是否为空
ifnot user_input:
print("⚠️ 请输入有效的计算式")
continue

            result = eval(user_input)

# 检查结果是否合法
ifisinstance(result, complex):
print("⚠️ 不支持复数运算")
elif result == float('inf'or result == float('-inf'):
print("⚠️ 结果超出可表示范围")
else:
print(f"✅ 计算结果: {result}")

except ZeroDivisionError:
print("❌ 错误: 除数不能为零!")
except SyntaxError:
print("❌ 语法错误: 请检查表达式格式")
print("   正确示例: 2 + 3 * 4")
except TypeError as e:
print(f"❌ 类型错误: {str(e)}")
print("   提示: 不能对字符串和数字直接运算")
except NameError as e:
print(f"❌ 变量错误: {str(e)}")
print("   提示: 表达式中不能包含未定义的变量")
except KeyboardInterrupt:
print("\n👋 程序被中断,退出计算器")
break
except Exception as e:
# 这是一个兜底catch,不应该经常触发
print(f"❓ 未知错误: {type(e).__name__}{str(e)}")
print("   如果持续出现此问题,请联系开发者")

defprint_help():
print("""
    📖 计算器帮助:
    - 加法: 2 + 3
    - 减法: 10 - 4
    - 乘法: 5 * 6
    - 除法: 8 / 2
    - 整除: 10 // 3
    - 取余: 10 % 3
    - 幂运算: 2 ** 10
    """
)

if __name__ == "__main__":
    calculator()

避坑要点:使用Exception作为兜底可以,但在此之前先处理具体的异常类型
这不仅更安全,代码可读性也更好


第三个坑:except不指定异常对象 - 老手也翻车的魔咒

场景重现:扫雷游戏的神秘崩溃

这是本文最核心的坑,也是我见过最多人翻车的

小甲鱼在开发扫雷游戏时,写了这样的代码:

defreveal_cell(x, y):
try:
        cell = board[x][y]
if cell.is_mine:
            explode()
else:
            count_mines = count_adjacent_mines(x, y)
            cell.reveal(count_mines)
except IndexError:
print("超出边界")

看起来很标准
捕获IndexError,处理边界问题

**但某天,玩家在边缘点击时,游戏没有提示"超出边界",而是直接闪退了
**

问题分析

等等,我刚才的代码不是已经捕获了IndexError

让我再仔细看看:

except IndexError:
print("超出边界")

**你没有把异常对象赋值给变量
**

虽然这行代码能正常捕获IndexError,但问题在于——如果你在try块里抛出的是其他异常呢
比如:

defreveal_cell(x, y):
try:
        cell = board[x][y]  # 抛出 IndexError
if cell.is_mine:    # 抛出 AttributeError
            explode()
else:
            count_mines = count_adjacent_mines(x, y)
            cell.reveal(count_mines)
except IndexError:
print("超出边界")

当玩家点击一个有问题的格子(比如cell对象没有正确初始化),代码会抛出AttributeError,但你的except只处理了IndexError

结果就是AttributeError没有被捕获,程序直接崩溃

解决方案

一定要指定异常对象,并且先处理最具体的异常

defreveal_cell(x, y):
try:
        cell = board[x][y]
if cell.is_mine:
            explode()
else:
            count_mines = count_adjacent_mines(x, y)
            cell.reveal(count_mines)
except IndexError as e:
print(f"超出边界: {e}")
except AttributeError as e:
print(f"格子数据错误: {e}")
# 这里应该记录日志并修复数据
except Exception as e:
print(f"未知错误: {type(e).__name__}{e}")
raise# 重新抛出,让上层处理

完整代码示例

classCell:
"""扫雷游戏中的格子"""
def__init__(self, x, y, has_mine=False):
self.x = x
self.y = y
self.has_mine = has_mine
self.revealed = False
self._mine_count = None

    @property
defis_mine(self):
"""安全访问mine属性"""
ifnothasattr(self'_has_mine'):
returnFalse
returnself._has_mine

    @is_mine.setter
defis_mine(self, value):
self._has_mine = value

defreveal(self, mine_count=0):
ifself.revealed:
returnFalse
self.revealed = True
self._mine_count = mine_count
returnTrue

def__str__(self):
ifnotself.revealed:
return"⬜"
ifself.has_mine:
return"💣"
ifself._mine_count == 0:
return"📂"
returnstr(self._mine_count)

classMinesweeper:
"""扫雷游戏主类 - 展示正确的异常处理"""

def__init__(self, width=8, height=8, mines=10):
self.width = width
self.height = height
self.mines = mines
self.board = [[Cell(x, y) for y inrange(height)] for x inrange(width)]
self.game_over = False
self._place_mines()

def_place_mines(self):
"""随机放置地雷"""
import random
        positions = [(x, y) for x inrange(self.width) for y inrange(self.height)]
        mine_positions = random.sample(positions, self.mines)
for x, y in mine_positions:
self.board[x][y].has_mine = True

defcount_adjacent_mines(self, x, y):
"""计算周围地雷数量"""
        count = 0
for dx in [-101]:
for dy in [-101]:
if dx == 0and dy == 0:
continue
try:
ifself.board[x + dx][y + dy].has_mine:
                        count += 1
except IndexError:
# 边缘情况,忽略
pass
return count

defreveal_cell(self, x, y):
"""点击格子 - 展示正确的异常处理"""
try:
# 第一个可能出错的点:数组越界
            cell = self.board[x][y]

# 第二个可能出错的点:属性访问
if cell.has_mine:
self.game_over = True
print("\n💥 BOOM!你踩到地雷了!")
self.print_board(reveal_all=True)
return

# 第三个可能出错的点:方法调用
            mine_count = self.count_adjacent_mines(x, y)
            cell.reveal(mine_count)

# 检查是否赢了
self._check_win()

except IndexError as e:
print(f"❌ 坐标超出范围: ({x}{y})")
print(f"   有效范围: x=[0, {self.width-1}], y=[0, {self.height-1}]")
except AttributeError as e:
print(f"❌ 格子数据异常: {str(e)}")
print("   正在尝试修复...")
self.board[x][y] = Cell(x, y, False)
except Exception as e:
print(f"❓ 未知错误: {type(e).__name__}{str(e)}")
raise# 重新抛出异常,让调用者知道

def_check_win(self):
"""检查是否获胜"""
        revealed_count = sum(
            cell.revealed 
for row inself.board 
for cell in row
        )
        total_cells = self.width * self.height
if revealed_count == total_cells - self.mines:
self.game_over = True
print("\n🎉 恭喜你!你赢了!")
self.print_board(reveal_all=True)

defprint_board(self, reveal_all=False):
"""打印棋盘"""
print("\n   " + " ".join(str(i) for i inrange(self.height)))
print("  " + "-" * (self.height * 2 + 1))
for x inrange(self.width):
print(f"{x}| ", end="")
for y inrange(self.height):
                cell = self.board[x][y]
if reveal_all or cell.revealed:
print(cell, end=" ")
else:
print("⬜", end=" ")
print()
print()

defplay_minesweeper():
"""扫雷游戏主循环"""
    game = Minesweeper(8810)

print("=" * 50)
print("💣 扫雷游戏 - 异常处理终极教学版")
print("输入坐标进行游戏,格式: x y")
print("输入 'q' 退出游戏")
print("=" * 50)
    game.print_board()

whilenot game.game_over:
try:
            user_input = input("请输入坐标 (如 3 4): ").strip()

if user_input.lower() in ('q''quit''exit'):
print("👋 游戏已退出")
break

# 解析输入
            parts = user_input.split()
iflen(parts) != 2:
print("⚠️ 请输入两个数字,用空格分隔")
continue

            x = int(parts[0])
            y = int(parts[1])

            game.reveal_cell(x, y)

ifnot game.game_over:
                game.print_board()

except ValueError:
print("❌ 请输入有效的数字")
except KeyboardInterrupt:
print("\n👋 游戏被中断")
break

if __name__ == "__main__":
    play_minesweeper()

避坑要点:这个坑的可怕之处在于——它不会每次都触发
代码在大多数情况下运行正常,只有特定边界条件下才会崩溃
所以很多老手也意识不到自己翻车了
记住:**永远用except Exception as e:,永远先处理具体异常,再处理通用异常
**


第四个坑:finally块中的危险操作 - 温柔陷阱

场景重现:游戏存档的诡异丢失

小甲鱼做了个游戏存档系统,用finally确保文件关闭:

defsave_game(filename):
    file = open(filename, 'w')
try:
# 保存游戏数据
        data = get_game_data()
        file.write(str(data))
finally:
        file.close()

看起来很完美
无论成功还是失败,文件都会关闭

**但如果get_game_data()抛出了异常呢
**

defsave_game(filename):
    file = open(filename, 'w')
try:
        data = get_game_data()  # 这里抛出异常!
        file.write(str(data))
finally:
        file.close()  # 会执行,但数据没保存

程序崩溃了,但finally块仍然执行了,文件被关闭了,但数据没有保存成功
用户丢失了游戏进度

问题分析

finally块的特性是:无论try块中发生什么,它一定会执行
这既是优点也是陷阱

常见错误:

  1. 1. 在finally中做关键操作(如保存数据、发送请求)
  2. 2. 期望在finally中捕获异常
  3. 3. 在finally中改变返回值

解决方案

关键操作放在try块中,使用上下文管理器

defsave_game(filename):
# 使用with语句,确保文件正确关闭
withopen(filename, 'w'as file:
# 保存游戏数据
        data = get_game_data()
        file.write(str(data))
# 如果到这里,说明保存成功
returnTrue

如果要处理异常:

defsave_game(filename):
try:
withopen(filename, 'w'as file:
            data = get_game_data()
            file.write(str(data))
returnTrue
except IOError as e:
print(f"保存失败: {e}")
returnFalse
except Exception as e:
print(f"未知错误: {e}")
returnFalse

完整代码示例

import json
import time

classGameSaveSystem:
"""游戏存档系统 - 展示finally的正确用法"""

def__init__(self):
self.save_slots = 3
self.saves = {}

defsave_game(self, slot, game_data):
"""保存游戏 - 正确版本"""
        filename = f"save_slot_{slot}.json"

# 验证存档槽位
if slot < 1or slot > self.save_slots:
raise ValueError(f"无效的存档槽位: {slot} (有效范围: 1-{self.save_slots})")

# 使用with语句,文件操作在try块内
try:
withopen(filename, 'w', encoding='utf-8'as f:
# 准备存档数据
                save_data = {
'timestamp': time.time(),
'game_state': game_data,
'version''1.0.0'
                }
# 写入数据
                json.dump(save_data, f, ensure_ascii=False, indent=2)

# 只有成功写入才更新内存记录
self.saves[slot] = save_data
print(f"✅ 游戏已保存到槽位 {slot}")
returnTrue

except PermissionError:
print(f"❌ 保存失败: 没有写入权限")
returnFalse
except IOError as e:
print(f"❌ 保存失败: {str(e)}")
returnFalse
except Exception as e:
print(f"❌ 保存失败: {type(e).__name__}{str(e)}")
returnFalse

defload_game(self, slot):
"""加载游戏"""
        filename = f"save_slot_{slot}.json"

try:
withopen(filename, 'r', encoding='utf-8'as f:
                save_data = json.load(f)

# 验证存档版本
if save_data.get('version') != '1.0.0':
print("⚠️ 存档版本不匹配,可能存在兼容性问题")

print(f"✅ 成功从槽位 {slot} 加载游戏")
return save_data['game_state']

except FileNotFoundError:
print(f"❌ 槽位 {slot} 没有存档")
returnNone
except json.JSONDecodeError as e:
print(f"❌ 存档文件损坏: {str(e)}")
returnNone
except Exception as e:
print(f"❌ 加载失败: {type(e).__name__}{str(e)}")
returnNone

defdelete_save(self, slot):
"""删除存档"""
import os
        filename = f"save_slot_{slot}.json"

try:
if os.path.exists(filename):
                os.remove(filename)
if slot inself.saves:
delself.saves[slot]
print(f"🗑️ 槽位 {slot} 的存档已删除")
else:
print(f"槽位 {slot} 没有存档")
except Exception as e:
print(f"❌ 删除失败: {str(e)}")

defdemo_save_system():
"""演示游戏存档系统"""
    system = GameSaveSystem()

print("=" * 50)
print("💾 游戏存档系统 - finally的正确用法")
print("=" * 50)

# 模拟游戏数据
    sample_game_state = {
'player': {'name''Hero''level'10'hp'100},
'position': {'x'50'y'75},
'inventory': ['sword''shield''potion']
    }

# 保存游戏
print("\n--- 保存游戏 ---")
    system.save_game(1, sample_game_state)

# 尝试加载
print("\n--- 加载游戏 ---")
    loaded_data = system.load_game(1)
if loaded_data:
print(f"玩家: {loaded_data['player']['name']}")
print(f"等级: {loaded_data['player']['level']}")

# 测试异常情况
print("\n--- 测试异常处理 ---")
    system.save_game(99, sample_game_data := {})  # 无效槽位

# 测试finally(通过异常)
print("\n--- finally的正确用法演示 ---")
try:
withopen("temp.txt""w"as f:
            f.write("test")
raise RuntimeError("模拟异常")
except RuntimeError:
print("异常被捕获,文件已正确关闭")
finally:
print("finally块执行 - 这里做清理工作,不要做关键操作")

if __name__ == "__main__":
    demo_save_system()

避坑要点finally块适合做清理工作(关闭文件、释放资源、断开连接),但不要在这里做关键操作(保存数据、发送请求)
记住:finally执行时,try块中的操作可能已经失败了


第五个坑:自定义异常的滥用 - 过度设计

场景重现:三层嵌套的自定义异常

小甲鱼决定要让自己的代码"更专业",于是定义了层层嵌套的自定义异常:

classGameError(Exception):
"""游戏基础异常"""
pass

classPlayerError(GameError):
"""玩家相关错误"""
pass

classPlayerNotFoundError(PlayerError):
"""玩家不存在"""
pass

classPlayerLevelTooLowError(PlayerError):
"""玩家等级太低"""
pass

classPlayerInventoryFullError(PlayerError):
"""背包满了"""
pass
# ... 还有20多个

然后使用的时候:

try:
    player = find_player(name)
    player.equip(item)
except PlayerNotFoundError:
print("玩家不存在")
except PlayerLevelTooLowError:
print("等级不够")
except PlayerInventoryFullError:
print("背包满了")
except PlayerError:
print("玩家相关错误")
except GameError:
print("游戏错误")
except Exception:
print("未知错误")

**三层嵌套之后,维护者(包括小甲鱼自己)已经完全不知道该怎么捕获异常了
**

问题分析

过度设计自定义异常的问题:

  1. 1. 异常类型太多,反而不知道用哪个
  2. 2. 维护成本高,每个新错误都要新建类
  3. 3. 大多数情况下,用内置异常就够了

解决方案

原则:内置异常优先,自定义异常用在特定领域

# 简单情况:用内置异常
if player isNone:
raise ValueError(f"玩家不存在: {name}")

if player.level < required_level:
raise ValueError(f"玩家等级不足: 需要{required_level}级,当前{player.level}级")

# 特定领域:用自定义异常
classGameError(Exception):
"""游戏业务相关的异常基类"""
pass

classSaveGameError(GameError):
"""存档相关错误"""
pass

完整代码示例

# 正确的自定义异常使用方式

# 1. 只定义业务相关的异常基类
classGameError(Exception):
"""游戏基础异常,所有游戏相关异常的父类"""
def__init__(self, message, error_code=None):
super().__init__(message)
self.error_code = error_code

# 2. 有限的具体异常(根据业务需求)
classSaveGameError(GameError):
"""存档操作失败"""
pass

classLoadGameError(GameError):
"""加载存档失败"""
pass

classGameLogicError(GameError):
"""游戏逻辑错误"""
pass

# 3. 游戏引擎示例
classPlayer:
"""玩家类 - 展示正确的异常使用"""

def__init__(self, name, level=1):
self.name = name
self.level = level
self._inventory = []
self._max_inventory = 20

defadd_item(self, item):
"""添加物品到背包"""
iflen(self._inventory) >= self._max_inventory:
# 使用ValueError,比自定义异常更清晰
raise ValueError(f"背包已满!当前: {len(self._inventory)}, 最大: {self._max_inventory}")

ifself.level < item.required_level:
raise GameLogicError(
f"等级不足: 需要{item.required_level}级,当前{self.level}级",
                error_code="LEVEL_TOO_LOW"
            )

self._inventory.append(item)
returnTrue

defremove_item(self, item_name):
"""移除物品"""
for i, item inenumerate(self._inventory):
if item.name == item_name:
returnself._inventory.pop(i)
raise ValueError(f"背包中没有物品: {item_name}")

classItem:
"""物品类"""
def__init__(self, name, required_level=1):
self.name = name
self.required_level = required_level

defdemo_correct_exception():
"""演示正确的异常使用方式"""

    player = Player("小甲鱼", level=5)

# 测试正常情况
    sword = Item("新手剑", required_level=1)
    armor = Item("皮甲", required_level=3)
    legendary_sword = Item("神器", required_level=10)

print("=" * 50)
print("🎮 异常处理最佳实践")
print("=" * 50)

# 添加低等级物品 - 成功
try:
        player.add_item(sword)
print(f"✅ 添加 {sword.name} 成功")
except Exception as e:
print(f"❌ 添加失败: {e}")

# 添加中等级物品 - 成功
try:
        player.add_item(armor)
print(f"✅ 添加 {armor.name} 成功")
except Exception as e:
print(f"❌ 添加失败: {e}")

# 添加高等级物品 - 失败(等级不足)
try:
        player.add_item(legendary_sword)
print(f"✅ 添加 {legendary_sword.name} 成功")
except GameLogicError as e:
print(f"❌ 游戏逻辑错误: {e}")
print(f"   错误代码: {e.error_code}")
except ValueError as e:
print(f"❌ 值错误: {e}")

# 模拟满背包
for i inrange(19):
        player.add_item(Item(f"物品{i}"))

try:
        player.add_item(Item("第20个物品"))
except ValueError as e:
print(f"\n❌ {e}")

if __name__ == "__main__":
    demo_correct_exception()

避坑要点:自定义异常是工具,不是装饰品
只有当内置异常无法准确描述你的业务错误时,才考虑自定义异常
而且层级不要超过两层(基类 + 具体类)


总结:5个避坑要点

好了,5个坑都讲完了
让我来总结一下最核心的避坑要点:

1. 永远不要用裸奔的except

# ❌ 错误
except:
print("出错了")

# ✅ 正确
except ValueError:
print("输入错误")

2. 先捕获具体异常,再捕获通用异常

# ❌ 错误
except Exception:
print("错误")

# ✅ 正确
except ValueError:
print("输入错误")
except Exception:
print("其他错误")

3. 永远指定异常对象

# ❌ 错误
except ValueError:
print("错误")

# ✅ 正确
except ValueError as e:
print(f"错误: {e}")

4. finally只做清理工作

# ❌ 错误
try:
    save_game()
finally:
# 不要在这里保存!
pass

# ✅ 正确
try:
withopen("save.txt""w"as f:
        save_game(f)
except IOError:
print("保存失败")

5. 内置异常优先,自定义异常克制

# ❌ 过度设计
classMyError(Exception): pass
classMyError1(MyError): pass
classMyError2(MyError): pass

# ✅ 简约设计
if x < 0:
raise ValueError("x必须为正")

行动建议

今天回去做两件事:

  1. 1. 打开你最近的Python项目,搜索except:except Exception:,把它们都改成具体的异常类型
  2. 2. 写一个扫雷游戏,把今天学的异常处理都用上去。边界检查、文件操作、用户输入——这些都是异常处理的好场景

代码不报错的时候,是学异常处理的最佳时机
等到真正出错再学,就晚了

有问题,欢迎在评论区留言
下期见

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-03-27 09:56:28 HTTP/2.0 GET : https://f.mffb.com.cn/a/483132.html
  2. 运行时间 : 0.087964s [ 吞吐率:11.37req/s ] 内存消耗:4,736.59kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=0097a196f7334d078eb3ff7ebb61545f
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000719s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000878s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000314s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000291s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000510s ]
  6. SELECT * FROM `set` [ RunTime:0.000209s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000586s ]
  8. SELECT * FROM `article` WHERE `id` = 483132 LIMIT 1 [ RunTime:0.003416s ]
  9. UPDATE `article` SET `lasttime` = 1774576588 WHERE `id` = 483132 [ RunTime:0.002797s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000237s ]
  11. SELECT * FROM `article` WHERE `id` < 483132 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000448s ]
  12. SELECT * FROM `article` WHERE `id` > 483132 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000408s ]
  13. SELECT * FROM `article` WHERE `id` < 483132 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.008366s ]
  14. SELECT * FROM `article` WHERE `id` < 483132 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001238s ]
  15. SELECT * FROM `article` WHERE `id` < 483132 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001016s ]
0.089556s