Asyncio调用在Gtk主循环中运行

时间:2014-10-31 12:58:23

标签: python gtk gtk3 python-asyncio

Okey们关于asyncio和Gtk +的问题。 如何在Gtk.main循环中运行下面的代码?我搜索了一些例子,但无法找到任何。

#!/usr/bin/python3.4

import asyncio

@asyncio.coroutine
def client_connected_handler(client_reader, client_writer):
    print("Connection received!")
    client_writer.write(b'Hello')
    while True:
        data = yield from client_reader.read(8192)
        if not data:
            break
        if 'EXIT' in data.decode():
            print("Closing server")
            break   
        print(data)
        client_writer.write(data)
    print('Server is closed')


loop = asyncio.get_event_loop()
Server=asyncio.start_server(client_connected_handler, 'localhost', 2222)
server=loop.run_until_complete(Server)
loop.run_forever()

编辑:

我应该用gbulb写下我的经验。 首先,我使用pip3搜索它。我发现它并试图安装它但由于链接不好而失败(我使用超级用户进行安装)。 接下来我从他们的存储库下载并安装它。我得到了这个example我运行它并在其核心模块中找到了缺少参数的错误。我不知道它究竟是哪个错误导致Iam写这个来自不同的PC我会尽快更新。如果有其他人可以测试它,我将不胜感激。

1 个答案:

答案 0 :(得分:10)

修改
截至2019年,gbulb库似乎是unmaintained。任何希望集成asyncio和GTK的人都应该只考虑答案的第二部分。

gbulb library旨在提供PEP 3156指定的asyncio事件循环与GLib主循环实现之间的连接器。 但是,当前的gbulb主服务器因Python 3.4附带的asyncio而中断。要解决此问题,您可以查看this fork而不是主文件。(该问题后来已在上游修复。)

使用工作gbulb,修改示例以接受传入连接并运行GTK是微不足道的:

#!/usr/bin/python3

import asyncio, gbulb
from gi.repository import Gtk
asyncio.set_event_loop_policy(gbulb.GLibEventLoopPolicy())

@asyncio.coroutine
def client_connected_handler(client_reader, client_writer):
    print("Connection received!")
    client_writer.write(b'Hello')
    while True:
        data = yield from client_reader.read(8192)
        if not data:
            break
        if 'EXIT' in data.decode():
            print("Closing server")
            break   
        print(data)
        client_writer.write(data)
    print('Server is closed')

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.start_server(client_connected_handler, 'localhost', 2222))

w = Gtk.Window()
w.add(Gtk.Label('hey!'))
w.connect('destroy', Gtk.main_quit)
w.show_all()

loop.run_forever()

另一种可能性是在不同的线程中运行asyncio事件循环:

#!/usr/bin/python3

import asyncio, threading
from gi.repository import Gtk

async def client_connected_handler(client_reader, client_writer):
    # ... unchanged ...

def run_asyncio():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(
        asyncio.start_server(client_connected_handler, 'localhost', 2222))
    loop.run_forever()

threading.Thread(target=run_asyncio).start()

w = Gtk.Window()
w.add(Gtk.Label('hey!'))
w.connect('destroy', Gtk.main_quit)
w.show_all()

Gtk.main()

这样做的好处是根本不需要gbulb(目前尚不清楚gbulb在生产中的测试情况。但是,需要注意使用线程安全函数在GUI(主)线程和asyncio线程之间进行通信。这意味着使用loop.call_soon_threadsafeasyncio.run_coroutine_threadsafe从GTK向asyncio提交内容,并GLib.idle_add从asyncio向GTK提交内容。