在Win10中将QEventLoop和asyncio默认循环与Python3配合使用时的不同行为

时间:2018-06-29 02:19:28

标签: python-3.x pyqt5 asyncsocket reconnect qeventloop

我正在使用PyQt5和Quamash从TCP服务器接收消息并将其显示在QTextBrowser中。

Fisrt, 如果(useQEventLoop = False,showGui = False)表示使用loop = asyncio.get_event_loop()并且不显示QMainWindow,则在TCP服务器关闭时,它仍然可以尝试继续使用TCP服务器重新连接到服务器打开。


Fri Jun 29 10:06:30 2018
Try to connect after 1 seconds...
Fri Jun 29 10:06:32 2018
Try to connect after 1 seconds...
Fri Jun 29 10:06:34 2018
Try to connect after 1 seconds...
Fri Jun 29 10:06:36 2018

然后, 如果(useQEventLoop = True,showGui = False),则在TCP服务器关闭时,它将引发以下无法捕获的错误,并停止重新连接到TCP服务器。


Fri Jun 29 10:07:37 2018
Event callback failed
Traceback (most recent call last):
  File "D:\Zibo\Documents\SRC\workspace\QHub\venv\lib\site-packages\quamash\_windows.py", line 42, in _process_events
    value = callback(transferred, key, ov)
  File "D:\Python35\Lib\asyncio\windows_events.py", line 509, in finish_connect
    ov.getresult()
ConnectionRefusedError: [WinError 1225]

最后, 如果(useQEventLoop = True,showGui = True)甚至先打开TCP服务器,套接字也会从TCP服务器回显该消息,但是它将停止使用新消息更新QTextBrowser。 如果有变化:

asyncio.run_coroutine_threadsafe(mw.update(), loop)

收件人:

asyncio.ensure_future(mw.update())

将引发附加异常,并且QTextBrowser中仍然没有消息更新。

1530238157.9816725
Fri Jun 29 10:09:17 2018
Task exception was never retrieved
future: <Task finished coro=<MainWindow.update() done, defined at D:\Zibo\Documents\SRC\workspace\QHub\vis\visstarter2.py:75> exception=RuntimeError('Task <Task pending coro=<MainWindow.update() running at D:\\Zibo\\Documents\\SRC\\workspace\\QHub\\vis\\visstarter2.py:78>> got Future <Future pending> attached to a different loop',)>
Traceback (most recent call last):
  File "D:\Python35\Lib\asyncio\tasks.py", line 242, in _step
    result = coro.throw(exc)
  File "D:\Zibo\Documents\SRC\workspace\QHub\vis\visstarter2.py", line 78, in update
    msg = await vq.get()
  File "D:\Python35\Lib\asyncio\queues.py", line 167, in get
    yield from getter
  File "D:\Python35\Lib\asyncio\futures.py", line 381, in __iter__
    yield self  # This tells Task to wait for completion.
RuntimeError: Task <Task pending coro=<MainWindow.update() running at D:\Zibo\Documents\SRC\workspace\QHub\vis\visstarter2.py:78>> got Future <Future pending> attached to a different loop

任何提示或信息将不胜感激。

代码如下:

import sys
import time
import asyncio
import logging
from quamash import QEventLoop
from PyQt5.QtWidgets import QApplication

logger = logging.getLogger(__name__)

async def visSender(w, q):
    while True:
        if q.qsize() > 0:
            msg = await q.get()
            if msg:
                try:
                    logger.debug(msg)
                    w.write(msg)
                    await w.drain()
                except ConnectionResetError:
                    break
        else:
            await asyncio.sleep(0.01)

async def startVis(vis_loop, vhost, vport, vq, qq):
    vwriter = None
    vsent = None
    while True:
        print(time.ctime())
        try:
            vreader, vwriter = await asyncio.open_connection(host=vhost, port=vport, loop=vis_loop)
            vsent = vis_loop.create_task(visSender(vwriter, vq))
            asyncio.ensure_future(vsent)
            #asyncio.run_coroutine_threadsafe(visSender(vwriter, qq), vis_loop)
            async for msg in vreader:
                await vq.put(msg)
                print(msg)
        except Exception as e:
            #logger.exception(e)
            print("Try to connect after 1 seconds...")
            if vsent:
                vsent.cancel()
            if vwriter:
                vwriter.close()
                vwriter = None
                vreader = None
            await asyncio.sleep(1) 


from PyQt5.QtWidgets import QMainWindow, QTextBrowser
class MainWindow(QMainWindow):
    def __init__(self, vq):
        QMainWindow.__init__(self)
        self.vq = vq
        self.centralwidget = QTextBrowser(self)
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.append("Starting...")


    async def update(self):
        while True:
            print(time.time())
            msg = await vq.get()
            self.centralwidget.append(msg.decode())
            await asyncio.sleep(0.01)




if __name__ == '__main__':
    vhost = "127.0.0.1"
    vport = 8848

    logger.setLevel(logging.DEBUG)

    vq = asyncio.Queue()
    qq = asyncio.Queue()

    useQEventLoop = True
    showGui = False
    if useQEventLoop:
        app = QApplication(sys.argv)
        loop = QEventLoop(app)
        asyncio.set_event_loop(loop)  # NEW must set the event loop
        if showGui:
            mw = MainWindow(vq)
            mw.show()
            #asyncio.run_coroutine_threadsafe(mw.update(), loop)
            asyncio.ensure_future(mw.update())
    else:
        loop = asyncio.get_event_loop()

    asyncio.run_coroutine_threadsafe(startVis(loop, vhost, vport, vq, qq), loop)
    try:
        loop.run_forever()
    except Exception as e:
        print(e)
        pending = asyncio.Task.all_tasks(loop)
        for task in pending:
            task.cancel()
    finally:
        loop.close()

0 个答案:

没有答案