Try-Except怎么用,3个追问解答在自动化下的应用

问1:什么是异常处理

异常处理(Try-Except)------给程序穿上防弹衣。

在真实环境里,你经常会遇到:某个子文件夹没权限访问(PermissionError)、某个文件刚好被同事删了(FileNotFoundError)、或者网络突然断了。

如果不加异常处理,只要有一个文件报错,整个扫描程序就会瞬间崩溃,直接闪退。


📌 知识点:怎么接住"报错"?

Python 的报错(Exception)是可以被"接住"的,语法结构长这样:

python 复制代码
try:
    # 把可能报错的代码放这里
    result = 10 / 0
except ZeroDivisionError:
    # 如果真的报了除零错误,就会跳到这里执行,程序不会崩
    print("你不能除以零!")
except Exception as e:
    # 兜底方案:所有你没预料到的错误,都会掉进这里
    print(f"发生了未知错误:{e}")

实战中最常用的就是 except Exception as e: 。它是一个大网,能网住所有的报错,并用变量 e 记录报错的具体原因。


🎮 怎么测试防弹衣有没有用?

你可以故意造一个错误:把 file.stat().st_size 改成 file.stat().st_size / 0(制造一个除法错误)。

运行一下,你会发现程序不会崩溃 ,而是控制台打印出一堆红色的 ERROR 日志,然后继续扫描下一个文件。这就是防弹衣的作用。

问2:try except Exception as e: 这个我用的还是比较多的,但是这个有没有比较有经验的用法,比如什么地方适合用,总不能每一行都用吧

答:"总不能每一行都用吧"------完全正确。 如果每行代码都包个 try...except,代码会变成一坨屎山,不仅难看,而且一旦真的出了严重 Bug,程序会悄悄吞掉错误,让你根本找不到原因。

在真正的工程开发中,老手用 try...except 有一个黄金法则:

只为"你无法控制的外部环境"兜底,不为"你自己的逻辑错误"擦屁股。

具体来说,有四个场景 适合用,两个场景绝对不要用:


✅ 适合用 try...except 的四个场景

1. 跟外部资源打交道时(最常用)

只要是去碰你的程序管不到的东西,就一定要包上:

  • 文件读写:文件被删了、权限不够、路径超长。

  • 网络请求:断网了、接口超时、服务器返回 500 错误。

  • 数据库:连接断了、唯一键冲突。

  • 硬件/外部设备:摄像头打不开、共享盘掉线。

2. 数据类型转换/解析时(防脏数据)

你从 Excel、CSV 或用户输入里拿到的数据,永远是脏的。比如你拿到的 "12.5%",你想转成 12.5:

python 复制代码
text = "12.5%"
try:
    num = float(text) # 如果遇到 "未填写",这里直接崩
except ValueError:
    num = 0.0 # 兜底
3. 调用别人的第三方库时

有些库写得很烂,动不动就抛个奇怪的异常,你如果不接住,整个程序直接死。你只能把调用的那几行包起来,防止它炸到你自己。

4. 多线程/多进程/批量处理时

就像你现在的 scanner.py,你正在批量扫 1000 个文件。第 500 个文件坏了,你不能让整个任务停下来。这时候的 try 是放在循环里面的,保证"死一个没关系,其他的继续跑"。


❌ 绝对不要用 try...except 的两个场景

1. 你自己的逻辑写错了,不要用

比如你写个函数,明确要求传 int,结果你手滑传了个 str。

你不要 用 try...except 去掩盖它。你应该让它直接报错(崩溃),然后去把传参的地方改对。

2. 可以用 if...else 提前判断的,不要用 try

比如,你要除以一个数:

python 复制代码
# ❌ 错误示范(用异常当流程控制)
try:
    result = a / b
except ZeroDivisionError:
    result = 0

# ✅ 正确示范(提前判断)
if b != 0:
    result = a / b
else:
    result = 0

"能预判的错误用 if,无法预判的意外用 try。"


🚀 老手的"高级用法"(避坑指南)

1. 尽量别用 except Exception as e 一把抓

虽然 Exception 能接住所有错,但太笼统了 。

如果代码里有拼写错误(NameError)或语法错误,你一把抓之后,错误被悄悄吞了,你还以为程序在正常跑。

老手会按顺序捕获具体的错误:

python 复制代码
try:
    file.stat()
except FileNotFoundError:
    logging.warning("文件消失了")
except PermissionError:
    logging.warning("没权限")
except Exception as e:
    # 实在不知道是啥错,兜底并记录,然后最好再抛出去
    logging.error(f"未知错误: {e}")
    raise # 把错误重新扔出去,让上层知道这里死了
2. 千万别写"静默吞掉"的代码
python 复制代码
# ❌ 极其恶劣的写法
try:
    do_something()
except:
    pass  # 出了错,当没看见,啥也不干

这叫"掩耳盗铃"。哪怕你什么处理都不做,也至少要在 except 里打个日志:

logging.error(f"出错了: {e}")。

3. 学会用 finally 清理战场

只要你打开了文件、连接了数据库、拿了锁,出了错也必须关上,否则会造成"资源泄漏"。用 finally 永远能执行最后一步:

python 复制代码
f = open("data.txt")
try:
    # 这里可能报错
    process(f) 
finally:
    f.close() # 不管上面错没错,必定关文件

(当然,用 with open 会更好,自动帮你做这一步)

这就是老手的"边界感":精准包裹高危区域,剩下的交给主程序自由奔跑。

问3:但是在涉及自动化的交互里,try怎么用呢,因为随时都在与外部资源打交道

在**自动化(RPA、爬虫、UI自动化)**里,几乎每一步都在和外部环境打交道:网页可能加载慢、按钮可能还没出来、API可能突然超时。

如果全用 try 包起来,代码确实会变成一座"屎山"。在自动化实战中,老手处理这种"随时可能出错"的场景,有三套非常经典的组合拳:


套路一:包装成"重试机制"(Retry)

自动化最怕网络抖动或页面卡顿。遇到这种错,不要直接跳过,而是"等几秒再试一次" 。

老手会写一个重试装饰器,或者直接用现成的库(比如 tenacity)。

python 复制代码
import time

def click_button_with_retry(driver, locator, max_retries=3):
    for attempt in range(max_retries):
        try:
            # 尝试找按钮并点击
            element = driver.find_element(*locator)
            element.click()
            return True # 成功了,直接结束函数
        except Exception as e:
            # 报错了,说明没找到或者点不动
            if attempt == max_retries - 1:
                # 最后一次也失败了,抛出错误,记录截图
                logging.error(f"重试 {max_retries} 次依然失败: {e}")
                raise 
            # 没到最后一次,等 2 秒再试
            time.sleep(2)

经验 :只把 try 放在这种**"尝试执行某个动作"**的局部函数里,而不是把整个流程包起来。


套路二:用于"分支判断"(元素存在性检测)

在 UI 自动化里,你经常会遇到弹窗。你不知道它什么时候弹,如果你直接用 find_element 去找,没找到就会直接抛异常崩溃。

这时 try 用来做**"静默探测"**:

python 复制代码
def close_ad_if_exists(driver):
    try:
        # 尝试找广告关闭按钮
        close_btn = driver.find_element(By.ID, "close-ad")
        close_btn.click()
        logging.info("发现广告,已关闭")
    except NoSuchElementException:
        # 找不到?说明没广告,不用管,当没看见
        pass # 这里的 pass 是合理的,因为找不到是预期内的事

套路三:阶梯兜底(降级策略)

比如你要抓一个网页的价格,你可以用 try 准备两套方案:

python 复制代码
try:
    # 方案A:尝试用精确的 CSS 选择器
    price = driver.find_element(By.CSS_SELECTOR, ".price-exact").text
except NoSuchElementException:
    # 方案B:方案A失败了,尝试用更宽泛的 XPath 兜底
    try:
        price = driver.find_element(By.XPATH, "//div[contains(@class, 'price')]").text
    except NoSuchElementException:
        # 彻底没救了,给个默认值,并且报警
        price = "0.00"
        logging.error("价格抓取失败,页面结构可能变了!")

🚨 自动化避坑铁律:绝不能"静默吞掉"

因为自动化是无人值守的(比如半夜跑脚本),所以老手绝不会在 except 里只写个 pass 就完事。

在自动化里,报错的 except 里必须做三件事:

  1. 打日志 :logging.error("xxx步骤出错")。

  2. 存现场 :如果是网页自动化,赶紧 driver.save_screenshot("error.png");如果是接口,把 response 存下来。

  3. 决定死活 :如果这一步极其关键(比如"登录"),失败了整个脚本跑下去也没意义,就直接 raise 抛出异常,终止任务;如果这一步无关紧要(比如"关闭广告"),就记个 log 继续往下走。

总结自动化的 try 核心哲学:

不要把它当成"避免崩溃"的万能药,把它当成"延长等待时间"和"准备备用方案"的工具。

只要你在 except 里能清楚回答:"失败了怎么办?是等几秒重试?是换条路走?还是截图报警?" ,你就不会乱用 try 了。

相关推荐
Cosolar2 小时前
极简智库:快速搭建你的开源项目教程阅读平台,让 docs/ 目录被更多人看见
java·架构·github
nice_lcj5202 小时前
【从零理解 Spring AI · 16】Agent 与工作流:什么该写死,什么该让模型决定
java·人工智能·后端·spring ai·ai应用开发
北京云帆互联科技2 小时前
云帆培训考试系统更新说明:v9.3.0
java·学习
学长毕设3 小时前
基于SpringBoot的景点管理系统-附源码
java·spring boot·后端
sxlishaobin4 小时前
Maven Setting详解
java·学习·maven
知守观4 小时前
一个方法两个触发口:反编译 XXL-Job 后,我看清了 inner/job 子包的裸奔现状
java·spring boot·微服务
用户3126874877204 小时前
CompletableFuture 链式编排:异步编程的优雅解法
java
瑞雪兆丰年兮5 小时前
JavaWeb-day14-SpringBootWeb原理篇
java·开发语言·spring boot·spring·bean·mybatis·javaweb
神仙别闹5 小时前
基于 Java GUI 贪心策略直接搜索算法和极大极小博弈树算法的智能人机博弈五子棋游戏
java·毕业设计·gui·贪心策略·极大极小博弈树