我创建了一个空的抽象类,AbstractStorage并Storage从中继承了该类:
AbstractStorage
Storage
import abc import pymongo as mongo host = mongo.MongoClient() print(host.alive()) # True class AbstractStorage(metaclass=abc.ABCMeta): pass class Storage(AbstractStorage): dbh = host def __init__(self): print('__init__') Storage()
我期望输出是
True __init__
但是,我得到的是
True Traceback (most recent call last): File "/home/vaultah/run.py", line 16, in <module> Storage() TypeError: Can't instantiate abstract class Storage with abstract methods dbh
如果我删除metaclass=abc.ABCMeta(这样AbstractStorage就变成一个普通的类)和/或如果我设置dbh了其他值,问题(显然)就消失了。
metaclass=abc.ABCMeta
dbh
这里发生了什么?
这实际上不是ABC的问题,而是PyMongo的问题。有一个关于它的问题在这里。似乎pymongo重写__getattr__以返回某种数据库类。这意味着将host.__isabstractmethod__返回一个数据库对象,该对象在布尔上下文中为true。这使ABCMeta认为这host是一种抽象方法:
__getattr__
host.__isabstractmethod__
host
>>> bool(host.__isabstractmethod__) True
问题报告中描述的解决方法是host.__isabstractmethod__ = False在对象上手动设置。关于这个问题的最后评论表明,已经为pymongo 3.0修复了问题。
host.__isabstractmethod__ = False