即使设置了属性,也没有属性错误

时间:2015-04-15 19:55:00

标签: python twisted

所以我有一个深入扩展两个类的类,这是它的定义和__init__()

class ProspectEventSocketProtocol(ChannelEventSocketProtocol):
    def __init__(self, *args, **kwargs):
        super(ProspectEventSocketProtocol, self).__init__(*args, **kwargs)
        self.channel_info = None

        self.rep_uuid = None
        self.manual_dial = None
        self.datetime_setup = timezone.now()
        self.datetime_answered = None
        self.defer_until_answered = defer.Deferred()
        self.defer_until_originated = defer.Deferred()
        self.defer_until_finished = defer.Deferred()

ChannelEventSocketProtocol的定义和__init__()在这里:

class ChannelEventSocketProtocol(Freeswitch):
    def __init__(self, *args, **kwargs):
        self.channel_driver = None
        self.uuid = kwargs.pop('uuid', str(uuid4()))
        self._call_driver = kwargs.pop('call_driver', None)
        super(ChannelEventSocketProtocol, self).__init__(*args, **kwargs)

Freeswitch类的定义和__init__()在这里:

class Freeswitch(client.EventSocketProtocol, TwistedLoggingMixin):
    def __init__(self, *args, **kwargs):
        self.jobs = {}
        self.defer_until_authenticated = defer.Deferred() # This is the problem
        client.EventSocketProtocol.__init__(self, *args, **kwargs)
        TwistedLoggingMixin.__init__(self)

即使我知道这个正在运行并且正在设置defer_until_authenticated以及它是callbackerrback,当我这样称呼时:

live_call = yield self._create_client_dial_live_call(client_dial.cid, client_dial.campaign)
pchannel = yield self.realm.get_or_create_channel_driver(live_call.uuid, 'prospect')
# ...
client_dial.prospect_channel = pchannel
yield pchannel.freeswitch_protocol.defer_until_authenticated # This is the problem here!

我收到错误:

type object 'ProspectEventSocketProtocol' has no attribute 'defer_until_authenticated'

我不知道为什么我再也无法获取该属性。我知道它已被设置,但我不知道它在哪里......或者它发生了什么。我搜索了错误,我不知道这个地方发生了什么。

仅供参考,以下是_create_client_dial_live_call()get_or_create_channel_driver()函数:

def _create_client_dial_live_call():
    # ...
    p, created = Prospect.objects.get_or_create_client_dial_prospect(campaign, cid_num)
    # ...
    live_call = LiveCall(prospect=p, campaign=campaign.slug)
    live_call.channel_vars_dict = chan_vars
    live_call.save()
    # ...

def get_or_create_channel_driver()
    # The code is kind of confusing with even more context, 
    # it basically either gets the existing ProspectChannel
    # object or creates a new one and then returns it.

1 个答案:

答案 0 :(得分:4)

某处某处忘记了实例化课程。

该错误并未告诉您类ProspectEventSocketProtocol的实例没有属性defer_until_authenticated。它告诉你类ProspectEventSocketProtocol本身没有这样的属性。

换句话说,你很可能正在编写像

这样的东西
pchannel.freeswitch_protocol = ProspectEventSocketProtocol

何时需要

pchannel.freeswitch_protocol = ProspectEventSocketProtocol(...)

代替。

这是一个快速演示脚本,可以重现您看到的错误消息:

#!/usr/bin/env python3

class Test(object):
    def __init__(self):
        self.arg = "1234"


correct = Test()
print(correct.arg)

wrong = Test
print(wrong.arg)

当我运行它时,我得到以下输出:

1234
Traceback (most recent call last):
  File "./type_object_error.py", line 12, in <module>
    print(wrong.arg)
AttributeError: type object 'Test' has no attribute 'arg'