Python脚本单独运行正常 导入时@classmethod报AttributeError
Python导入模块后调用类方法触发AttributeError的排查与修复
问题复现
在树莓派环境下使用Python3复用CoderBot项目代码搭建自主网页控制机器人时,将问题简化为如下测试代码:
第一个文件为ct.py,实现了一个带类方法的单例类:
class myclass(): objClass = None def __init__(self): print("initialised") @classmethod def get_it(cls): if not cls.objClass: print("objClass does not exist") cls.objClass = myclass() print("created") return cls.objClass def main(args): method_list = [method for method in dir(myclass) if method.startswith('_') is False] print(method_list) makeone = myclass.get_it() print(makeone) print(myclass.get_it()) return 0 if __name__ == '__main__': import sys sys.exit(main(sys.argv))
单独运行ct.py时输出完全符合预期:
['get_it', 'objClass'] objClass does not exist initialised created <__main__.myclass object at 0x7fbe6e1fa0> <__main__.myclass object at 0x7fbe6e1fa0>
在同目录下新建第二个脚本导入ct模块运行,代码如下:
import ct def main(args): method_list = [attribute for attribute in dir(ct.myclass) if callable(getattr(ct.myclass, attribute)) and attribute.startswith('__') is False] print(method_list) two = ct.get_it() return 0 if __name__ == '__main__': import sys sys.exit(main(sys.argv))
运行后抛出如下错误:
['get_it'] Traceback (most recent call last): File "/home/pi/classTest/mainct.py", line 35, in <module> sys.exit(main(sys.argv)) File "/home/pi/classTest/mainct.py", line 30, in main two = ct.get_it() AttributeError: module 'ct' has no attribute 'get_it'
从打印的方法列表可以看到get_it确实存在于myclass类中,但调用时触发属性不存在错误。
根因分析
报错的核心原因是属性归属层级判断错误:
get_it是定义在myclass下的类方法,属于myclass类的属性,并非ct模块的顶层属性- 代码中写
ct.get_it()是尝试直接从模块顶层查找该方法,查找路径错误,自然无法找到对应属性触发报错。
修复方法
按照正确的属性层级调用即可,有两种常用写法:
- 写法1:导入整个模块,通过
模块名.类名.方法名的完整路径调用
import ct two = ct.myclass.get_it()
- 写法2:直接从模块中导入目标类,再通过类名调用类方法
from ct import myclass two = myclass.get_it()
注:排查过程中记录的
from myclass import MyClass为路径笔误,实际类定义在ct.py文件中,类名为myclass,导入时需要和实际定义的路径、名称保持一致。
修改后即可正常调用类方法获取单例对象,不会再触发属性不存在的报错。
内容的提问来源于stack exchange,提问作者Steve Gale
相关产品推荐
相关产品推荐

