微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Discord Python,在调用 client.close() 之后,我希望能够再次调用 client.start(),但不知何故客户端多次登录

如何解决Discord Python,在调用 client.close() 之后,我希望能够再次调用 client.start(),但不知何故客户端多次登录

我正在尝试使用基于 Qt 的 GUI 构建 discord Bot。我想要两个按钮,一个启动机器人,一个停止它。当我在 client.close() 后重新启动时,Bot 使用多个实例登录,但我不知道如何修复它。

代码

import bot # some discord bot that can login on a server and send a message
import asyncio
from PySide6.QtWidgets import QLabel,QWidget,QPushButton,QTextbrowser,QComboBox
from qasync import QEventLoop,asyncslot,QApplication
from PySide6.QtCore import QFile
from PySide6.QtUiTools import quiloader
import PySide6.QtGui as QtGui

class main(QWidget):
    def __init__(self):
        super(main,self).__init__(Parent=None)
        self.load_ui()
        self.btn_startbot = self.findChild(QPushButton,'btn_startbot')
        self.btn_startbot.clicked.connect(self.on_btn_startbot_clicked)
        self.btn_stopbot = self.findChild(QPushButton,'btn_stopbot')
        self.btn_stopbot.clicked.connect(self.on_btn_stopbot_clicked)

    def load_ui(self):
        loader = quiloader()
        ui_file = QFile("form.ui") # some ui,that has buttons
        ui_file.open(QFile.ReadOnly)
        loader.load(ui_file,self)
        ui_file.close()


    @asyncslot()
    async def on_btn_startbot_clicked(self):
        print("clicked start bot")
        self.bot = bot.MyBot(command_prefix='-',self_bot=False)
        self.bot.sig_slot_handler.sig_send_log.connect(self.slot_log_msg)
        await self.bot.start('Token') 
    
    @asyncslot()
    async def on_btn_stopbot_clicked(self):
        await self.bot.close()

    @asyncslot(str)
    async def slot_log_msg(self,logmsg):
        print(logmsg) 

我不知道这是否与事件循环有关,但我需要使用 qasync,因为 Qt 事件循环和 discord 的 async 事件循环发生冲突。

if __name__ == "__main__":
    app = QApplication([])
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    widget = main()
    widget.show()
    loop.run_forever()

最小机器人类:

class MyBot(commands.Bot):
    sig_slot_handler = q_signal_slot_handler()

    def __init__(self,command_prefix,self_bot,parent=None):
        commands.Bot.__init__(self,command_prefix=command_prefix,self_bot=self_bot)
        self.add_commands()
        self.add_events()
    
    def add_events(self):

        @self.event
        async def on_ready():
            self.sig_slot_handler.send_log_signal(f'PyBot login') 

    def add_commands(self):
        @self.command(brief="Send a Message",usage="<MESSAGE WORDS>",help="Send a Message in your active Text Channel. Type: -send <MESSAGE WORDS>")
        async def send(ctx,*,message):
            await ctx.message.delete()
            self.sig_slot_handler.send_log_signal(f'{ctx.author} used send in {ctx.message.channel}.')
            await ctx.send(message)

我还创建了一个类来处理 Qt 信号和插槽:

class q_signal_slot_handler(QObject):
    sig_send_log    = Signal(str)

    def __init__(self,Parent=None):
        super(q_signal_slot_handler,self).__init__(Parent=Parent)
    
    def send_log_signal(self,logmsg):
        self.sig_send_log.emit(logmsg)

在我按下停止然后重新开始后会发生什么,输出是这样的:

解决方法

问题是 sig_slot_handler 是所有 MyBot 的单个对象,因此您多次连接相同的信号,因此当发出信号时,将多次调用插槽。解决办法是把类的一个属性做成sig_slot_handler:

class MyBot(commands.Bot):
    def __init__(self,command_prefix,self_bot,parent=None):
        commands.Bot.__init__(self,command_prefix=command_prefix,self_bot=self_bot)
        self.sig_slot_handler = q_signal_slot_handler()
        self.add_commands()
        self.add_events()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。