You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保Selenium脚本B在所有场景下执行driver.quit()?

问题背景

我通过Python脚本A的subprocess.Popen启动了运行Selenium自动化的Python脚本B。脚本B运行时存在三种场景:

  1. 脚本B正常完成任务;
  2. 脚本B执行时崩溃;
  3. 脚本A调用taskkill终止脚本B。

已知场景1可在末尾调用driver.quit(),场景2可使用try-except-finally处理,但场景3下,脚本A用以下代码强制终止B时,怎么确保B能执行driver.quit()?

subprocess.call(['taskkill', '/F', '/T', '/PID',  str(processB.pid)])
解决思路与实现方法

首先明确:taskkill /F是强制终止进程,这种情况下脚本B会被直接杀死,根本没机会执行任何收尾代码。核心解决思路是避免硬终止,改成让脚本B主动响应终止信号并执行清理,或者用兜底的监控方案。

方案1:改用软终止信号(推荐)

把强制终止改成发送可捕获的终止信号,让脚本B有机会执行driver.quit()。

脚本A的修改

替换原来的taskkill /F调用,改成发送Ctrl+C对应的控制台信号(Windows环境):

import win32api
import win32con

# 给脚本B发送Ctrl+C信号,触发其信号处理逻辑
win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT, processB.pid)
# 等待脚本B自行完成退出
processB.wait()

# 如果上述方法无效,可降级为非强制的taskkill(不加/F参数)
# subprocess.call(['taskkill', '/T', '/PID', str(processB.pid)])

脚本B的修改

在脚本B中注册信号处理函数,捕获终止信号并执行浏览器清理:

import signal
from selenium import webdriver

driver = None

def clean_up(signum, frame):
    global driver
    if driver:
        driver.quit()
    exit(0)

# 注册信号处理:捕获Ctrl+C(SIGINT)和通用终止信号(SIGTERM)
signal.signal(signal.SIGINT, clean_up)
signal.signal(signal.SIGTERM, clean_up)

try:
    driver = webdriver.Chrome()
    # 你的Selenium自动化业务逻辑
finally:
    # 覆盖正常结束和崩溃场景的清理
    if driver:
        driver.quit()

方案2:强制终止下的兜底监控(仅万不得已时用)

如果必须用taskkill /F,可以在脚本B中启动一个独立的监控子进程,当检测到B的主进程被杀死后,负责关闭浏览器驱动。

脚本B的实现

import os
from selenium import webdriver
import subprocess

driver = webdriver.Chrome()
current_pid = os.getpid()
# 获取浏览器驱动的进程PID
driver_pid = driver.service.process.pid

# 启动监控脚本,传入主进程PID和驱动PID
subprocess.Popen(['python', 'monitor.py', str(current_pid), str(driver_pid)])

try:
    # 你的自动化逻辑
finally:
    if driver:
        driver.quit()

监控脚本monitor.py的实现

import os
import time
import sys
import subprocess

def main():
    parent_pid = int(sys.argv[1])
    driver_pid = int(sys.argv[2])
    
    while True:
        try:
            # 检查主进程是否存活
            os.kill(parent_pid, 0)
        except OSError:
            # 主进程已死,强制关闭浏览器驱动
            subprocess.call(['taskkill', '/F', '/PID', str(driver_pid)])
            break
        time.sleep(1)

if __name__ == "__main__":
    main()

关键提醒

  • 尽量不要用taskkill /F,硬终止等于直接断电,任何进程都没法执行收尾代码;
  • 方案2的监控脚本是兜底方案,缺点是多启动了一个进程,且依赖浏览器驱动PID的正确获取。

内容的提问来源于stack exchange,提问作者Gordian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:09:16