Twisted编写字母倒计时脚本触发a is not callable报错求解
报错原因
报错的直接触发原因是reactor.callLater的参数使用错误:
Twisted的callLater接口签名为reactor.callLater(delay_seconds, callable_obj, *args, **kwargs),第二个位置参数必须传入可执行的对象(函数、方法、实现了__call__的类实例等),后续参数才是传给这个可执行对象的入参。你的代码里传入的是遍历得到的字符串l(第一次循环时l的值为'a'),字符串不是可调用对象,Twisted内部做参数校验时就会抛出a is not callable的断言错误。
除此之外你的代码还有3个逻辑问题,就算修复了参数错误也无法达到预期效果:
- 拼写错误:停止reactor的代码写为
rector.stop(),漏写了字符a,执行到z时会触发NameError - 循环逻辑错误:
countletters方法里的for循环是同步瞬时执行完成的,不会等待1秒延时,相当于一瞬间就把25个延时任务全部注册到事件循环,哪怕参数正确,也会在1秒后一次性输出所有a-y的字母,无法实现逐字母间隔1秒输出的效果 - 输出逻辑遗漏:判断到当前字母是
z时直接停止reactor,没有打印z本身
修复方法
逐字母延时输出不能用同步for循环批量注册任务,需要改成链式调用逻辑:每次打印完当前字母后,再注册1秒后执行下一次打印的任务,直到打印到z再停止reactor。修正后的可运行代码如下:
from twisted.internet import reactor class Countletters(object): letters = list(map(chr, range(97, 123))) def __init__(self): self.pointer = 0 def count(self): current = self.letters[self.pointer] print(current) if current == 'z': reactor.stop() return self.pointer += 1 reactor.callLater(1, self.count) if __name__ == "__main__": counter = Countletters() reactor.callWhenRunning(counter.count) print('Start countdown') reactor.run() print('Stop countdown')
修复点对应说明:
- 传给
callLater的第二个参数改为实例方法self.count,属于可调用对象,解决断言报错 - 修正了reactor的拼写错误
- 用指针属性记录当前打印到的字母位置,每次打印完成后延时1秒调用自身打印下一个字母,实现逐秒输出的效果
- 调整判断顺序:先打印当前字母,再判断是否为z,保证z可以正常输出后再停止事件循环
内容的提问来源于stack exchange,提问作者tesla john
相关产品推荐
相关产品推荐

