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

Python 3.7中能否统计函数运行时长并在超时时自动终止

Python 3.7 实现函数运行时长统计+超时自动终止的方案

可以实现,下面分两种常用场景给出可直接运行的代码示例:

方案1:Unix/Linux/macOS 专用(实现更轻量)

基于系统SIGALRM信号实现,不需要额外依赖,性能损耗极低:

import signal
import time
from functools import wraps

# 自定义超时异常
class TimeoutError(Exception):
    pass

def timeout(seconds):
    def decorator(func):
        # 超时触发的回调函数
        def _handle_timeout(signum, frame):
            raise TimeoutError(f"函数运行超时,设定阈值为{seconds}秒")
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 注册SIGALRM信号的处理函数
            signal.signal(signal.SIGALRM, _handle_timeout)
            # 设定闹钟,seconds秒后发送SIGALRM信号
            signal.alarm(seconds)
            start_time = time.perf_counter()
            try:
                result = func(*args, **kwargs)
            finally:
                # 取消闹钟
                signal.alarm(0)
                # 计算运行时长
                run_duration = time.perf_counter() - start_time
                print(f"函数{func.__name__}实际运行时长:{run_duration:.2f}秒")
            return result
        return wrapper
    return decorator

# 测试示例
@timeout(3) # 设定超时阈值为3秒
def test_func(delay):
    time.sleep(delay)
    return "运行完成"

if __name__ == "__main__":
    try:
        print(test_func(2)) # 延迟2秒,不会超时
        print(test_func(5)) # 延迟5秒,会触发超时
    except TimeoutError as e:
        print(e)
  • 限制:Windows系统不支持SIGALRM信号,无法使用该方案

方案2:跨平台通用(兼容Windows)

基于多进程实现,把目标函数放到子进程运行,主进程监控时长,超时直接终止子进程:

import time
import multiprocessing
from functools import wraps

class TimeoutError(Exception):
    pass

def timeout(seconds):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 定义子进程运行的包装,把返回值存在队列里
            def run_func(queue, *args, **kwargs):
                try:
                    res = func(*args, **kwargs)
                    queue.put(res)
                except Exception as e:
                    queue.put(e)
            
            queue = multiprocessing.Queue()
            start_time = time.perf_counter()
            p = multiprocessing.Process(target=run_func, args=(queue, *args), kwargs=kwargs)
            p.start()
            # 等待子进程运行,最多等seconds秒
            p.join(seconds)
            
            run_duration = time.perf_counter() - start_time
            print(f"函数{func.__name__}实际运行时长:{run_duration:.2f}秒")
            
            # 如果子进程还在运行,就强制终止
            if p.is_alive():
                p.terminate()
                p.join()
                raise TimeoutError(f"函数运行超时,设定阈值为{seconds}秒")
            # 从队列里取结果
            result = queue.get()
            if isinstance(result, Exception):
                raise result
            return result
        return wrapper
    return decorator

# 测试示例
@timeout(3)
def test_func(delay):
    time.sleep(delay)
    return "运行完成"

if __name__ == "__main__":
    try:
        print(test_func(2))
        print(test_func(5))
    except TimeoutError as e:
        print(e)
  • 注意事项:被装饰的函数参数和返回值必须是可序列化的(Python pickle模块支持的类型),否则会运行报错
  • 小缺点:进程启停会有毫秒级的额外开销,对计时精度要求极高的场景可以根据情况忽略

内容的提问来源于stack exchange,提问作者Crisóstomo Musa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:15:03