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

Heroku部署discord.py机器人报InterruptableThread无isAlive属性错误

问题描述

近期我参照教程为自己的discord.py机器人编写超时控制函数,避免单条命令执行耗时过长占用机器人资源,该命令依赖的逻辑在bot.py文件顶部导入的独立脚本中实现。

  • 本地运行环境:Windows 10,微软商店安装的Python版本,执行py bot.py启动时超时功能正常
  • 部署环境:Heroku平台,通过heroku run bash进入环境执行python bot.py启动后,触发calculator命令抛出如下错误:
Ignoring exception in command calculator:
Traceback (most recent call last):
(traceback...)

AttributeError: 'InterruptableThread' object has no attribute 'isAlive'

The above exception was the direct cause of the following exception:
(more traceback...)

超时函数基于Python标准库threading实现,代码如下:

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
    class InterruptableThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.result = None

        def run(self):
            try:
                self.result = func(*args, **kwargs)
            except:
                self.result = default

    it = InterruptableThread()
    it.start()
    it.join(timeout_duration)
    if it.isAlive():
        raise TimeLimitExpired()
    else:
        return it.result

函数调用方式如下,参数TIMEOUT值设为5:

timeout(interpreter.visit, (ast.node, context), timeout_duration=TIMEOUT, 
default=RuntimeResult().failure("Execution timed out."))

报错原因

报错是本地和Heroku环境的Python版本不一致导致的:

  • 旧版Python(3.8及更早版本)的threading.Thread类保留了驼峰命名的isAlive()方法作为兼容别名,本地安装的Python版本属于这个范围,所以代码可以正常运行
  • 从Python 3.9版本开始,官方正式移除了已经废弃多年的isAlive()别名,只保留符合PEP8规范的蛇形命名is_alive()方法。Heroku默认部署使用的Python版本为3.9+,因此找不到isAlive属性抛出AttributeError。

修复方案

直接将代码中判断线程存活状态的it.isAlive()替换为标准的it.is_alive()即可,该写法兼容所有仍在维护的Python版本,修复后的完整超时函数如下:

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
    class InterruptableThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.result = None

        def run(self):
            try:
                self.result = func(*args, **kwargs)
            except:
                self.result = default

    it = InterruptableThread()
    it.start()
    it.join(timeout_duration)
    if it.is_alive():
        raise TimeLimitExpired()
    else:
        return it.result

补充说明:当前基于线程join的超时实现,仅能让主线程在超时后不再等待子线程返回,无法真正终止仍在后台运行的超时任务,长时间运行还是会占用资源。如果需要彻底终止超时任务,需要改用支持任务取消的协程方案或者多进程方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:51:20