You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

QThread内multiprocessing进程无法优雅终止Robot Framework脚本问题

解决QThread内启动的Robot Framework进程无法优雅终止(执行Teardown)的问题

我之前碰到过类似的场景,核心问题其实出在终止进程时发送的信号类型上:你之前用terminate()会给进程发送SIGTERM信号,但Robot Framework默认只监听SIGINT(也就是用户按下Ctrl+C触发的信号)来触发优雅退出,执行Suite/Test Teardown流程。而主进程直接启动的进程能正常执行Teardown,本质是因为Robot对SIGINT的处理逻辑,而非主进程的环境差异。

具体解决方案

我们需要修改RobotExec类的stop方法,替换terminate()为发送SIGINT信号(Windows系统需要特殊处理,因为没有直接的SIGINT发送方式):

1. 修改robotrunner.py代码

首先导入必要的模块:

import signal
import sys
import ctypes

然后修改RobotExecstop方法:

def stop(self):
    print("Sending graceful terminate signal to Robot process")
    if sys.platform == 'win32':
        # Windows系统需要发送控制台Ctrl+C事件
        # GenerateConsoleCtrlEvent会给同一控制台组的进程发送信号,所以要让主进程忽略这个信号
        ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, self.p.pid)  # 0代表CTRL_C_EVENT
    else:
        # Linux/macOS直接发送SIGINT信号
        self.p.send_signal(signal.SIGINT)
    print("Waiting to join")
    self.p.join()
    print("joined")

另外,在主进程入口处添加Windows下的信号忽略处理,避免GUI进程被误杀:

if __name__ == '__main__':
    # Windows下让主进程忽略SIGINT,防止发送Ctrl+C事件时影响GUI
    if sys.platform == 'win32':
        signal.signal(signal.SIGINT, signal.SIG_IGN)
    
    test=2 #Choose between 1 and 2
    print(test)
    # ... 后面的代码保持不变

为什么这样能解决问题?

  • Robot Framework的robot.run()内部已经实现了对SIGINT信号的处理:当收到这个信号时,它会停止当前执行的测试,然后依次执行所有配置的Teardown流程,最后优雅退出。
  • terminate()默认发送的SIGTERM信号,Robot Framework没有做特殊处理,进程会被直接杀死,自然无法执行Teardown。
  • Windows系统没有SIGINT的直接发送接口,所以需要用GenerateConsoleCtrlEvent模拟用户按下Ctrl+C的操作,同时让主进程忽略这个信号,避免GUI被终止。

测试验证

修改完代码后,将test设为2运行,你会看到控制台输出Teardown Suite相关的日志,说明Teardown流程已经正常执行了。

额外注意点

  • 如果你的Robot脚本里有自定义的信号处理逻辑,需要确保它不会覆盖Robot Framework默认的SIGINT处理。
  • 在Windows下,确保Robot进程和主进程在同一控制台组(默认multiprocessing创建的进程会继承控制台组,所以没问题)。

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

火山引擎 最新活动