gpt4 book ai didi

python - 如何将 asyncio 任务添加到 pyqt5 事件循环,以便它运行并避免从未等待的错误?

转载 作者:行者123 更新时间:2023-12-02 16:14:30 25 4
gpt4 key购买 nike

我是 asyncio 的新手,我想在我的 pyqt 应用程序中利用它来处理通过 tcp 连接进行的通信。

我做了这个简单的演示来学习如何在异步上下文中处理 QT 循环。我看过其他与此相关的帖子,但它们比我现在尝试做的要复杂得多。因此,我在一个单独的窗口中启动服务器客户端,以便它进行监听,并尝试通过我的小部件上的简单按钮单击事件发送消息。尽其所能....我的问题是它不起作用。

我希望能够进行一次信息交换以及端口为流打开的情况。我认为这些任务在 asyncio 中会很简单,但在这一点上让它与 qt 很好地配合似乎很困难。

现在我得到

RuntimeWarning: coroutine 'PushButton.sendmessage' was never awaited
rslt = self.__app.exec_()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

我不确定从哪里开始解决这个问题。

测试.py

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, pyqtSlot
import sys
import asyncio
from asyncqt import QEventLoop
from async_client import tcp_echo_client


class PushButton(QWidget):

loop = None

def __init__(self,app_loop):
super(PushButton,self).__init__()
self.initUI()
self.loop = loop

def initUI(self):
self.setWindowTitle("PushButton")
self.setGeometry(400,400,300,260)
self.send_bttn = QPushButton(self)
self.send_bttn.setText("SEnd Message")
self.send_bttn.clicked.connect(self.sendmessage)
self.send_bttn.move(100,100)

@pyqtSlot()
async def sendmessage(self):
run_command = asyncio.create_task(tcp_echo_client("hey",self_loop))
asyncio.run(run_command)



if __name__ == '__main__':
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop) # NEW must set the event loop sys.exit(app.exec_())

ex = PushButton(loop)
ex.show()
with loop:
loop.run_forever()

简单的回显客户端例程

import asyncio


async def tcp_echo_client(message, loop):
reader, writer = await asyncio.open_connection('127.0.0.1', 8889,
loop=loop)

print('Send: %r' % message)
writer.write(message.encode())

data = await reader.read(100)
print('Received: %r' % data.decode())

print('Close the socket')
writer.close()

和响应服务器


import asyncio

async def handle_echo(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print("Received %r from %r" % (message, addr))

print("Send: %r" % message)
writer.write(data)
await writer.drain()

print("Close the client socket")
writer.close()

loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_echo, '127.0.0.1', 8889, loop=loop)
server = loop.run_until_complete(coro)

# Serve requests until Ctrl+C is pressed
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass

# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

最佳答案

问题是,如果你调用一个协程槽,那么你必须使用 asyncSlot 装饰器,也不要使用 ayncion.run()await(除了消除其他拼写错误)。

import sys
import asyncio

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

from asyncqt import QEventLoop, asyncSlot
from async_client import tcp_echo_client


class PushButton(QWidget):

loop = None

def __init__(self, loop=None):
super(PushButton, self).__init__()
self.initUI()
self.loop = loop or asyncio.get_event_loop()

def initUI(self):
self.setWindowTitle("PushButton")
self.setGeometry(400, 400, 300, 260)
self.send_bttn = QPushButton(self)
self.send_bttn.setText("SEnd Message")
self.send_bttn.clicked.connect(self.sendmessage)
self.send_bttn.move(100, 100)

@asyncSlot()
async def sendmessage(self):
await tcp_echo_client("hey", self.loop)


if __name__ == "__main__":
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)

ex = PushButton(loop)
ex.show()
with loop:
loop.run_forever()

关于python - 如何将 asyncio 任务添加到 pyqt5 事件循环,以便它运行并避免从未等待的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67152552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com