【问题标题】:Python callback not called when using class使用类时未调用 Python 回调
【发布时间】:2020-07-23 15:22:35
【问题描述】:

这是我的代码:

import asyncio
import logging
from asyncio import AbstractEventLoop

from aio_pika import connect, IncomingMessage


def test_one(a, b):
    print("test_one", a, b)


class Consumer:
    def __init__(self, url):
        self.url = url

    async def run(self, loop: AbstractEventLoop):
        while True:
            try:
                connection = await connect(self.url, loop=loop)
                connection.add_close_callback(test_one)
                connection.add_close_callback(self.test_two)

                # Creating a channel
                channel = await connection.channel()

                # Declaring queue
                queue = await channel.declare_queue("snapshots")

                logging.info("Started listening")

                # Start listening the queue with name 'hello'
                await queue.consume(self.on_message, no_ack=True)
                break
            except:
                logging.error("Could not connect")
            finally:
                await asyncio.sleep(1)

    def on_message(self, message: IncomingMessage):
        print(message.body)

    def test_two(self, a, b):
        print("closed", a, b)

我的问题是当我断开连接时它只调用 test_one 函数,但它不调用类内的 test_two 函数。我不明白。我尝试只添加 test_two 函数,但这也不起作用。尝试删除参数。同样的问题。我没主意了。你知道我做错了什么吗?

顺便说一句 self.on_message 确实有效。

【问题讨论】:

  • 我正在努力解决类似的问题。如果我在 Main 中调用一个类函数,它就可以工作。如果我在模块中调用静态函数,它就可以工作。但是如果我在一个模块中调用一个类函数,它不会。你找到解决问题的方法了吗?
  • @VoteCoffee 您好,不,我没有找到解决方案并放弃了。后来决定用另一种语言再试一次。
  • 也许试试 lambda 函数?
  • 原来我使用的 API 正在创建对回调函数的弱引用,并且底层回调函数句柄在 API 尝试使用它之前就被破坏了。在将回调函数传递给 API 之前,我通过将回调函数存储为类中的 self._callbackfunction 变量来解决它。费了很多功夫才弄明白!

标签: python python-3.x callback


【解决方案1】:

API 可能正在创建对正在传递的回调函数的弱引用。尝试在传递回调函数之前创建一个强引用。

self._cb_func = self.test_two
connection.add_close_callback(self._cb_func)

完整代码:

import asyncio
import logging
from asyncio import AbstractEventLoop

from aio_pika import connect, IncomingMessage


def test_one(a, b):
    print("test_one", a, b)


class Consumer:
    def __init__(self, url):
        self.url = url

    async def run(self, loop: AbstractEventLoop):
        while True:
            try:
                connection = await connect(self.url, loop=loop)
                connection.add_close_callback(test_one)
                self._cb_func = self.test_two
                connection.add_close_callback(self._cb_func)

                # Creating a channel
                channel = await connection.channel()

                # Declaring queue
                queue = await channel.declare_queue("snapshots")

                logging.info("Started listening")

                # Start listening the queue with name 'hello'
                await queue.consume(self.on_message, no_ack=True)
                break
            except:
                logging.error("Could not connect")
            finally:
                await asyncio.sleep(1)

    def on_message(self, message: IncomingMessage):
        print(message.body)

    def test_two(self, a, b):
        print("closed", a, b)

如果你有很多回调函数,那么在这个问题中有一个答案是将它们存储为数组:using python WeakSet to enable a callback functionality

【讨论】:

  • 没有测试它,因为几个月前放弃了这个项目,但我相信你这是正确的解决方案:)。
  • @DazDylz 不用担心,正是我的问题的解决方案让我想到了类似的问题。希望它可以帮助某人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 2019-08-12
相关资源
最近更新 更多