Asyncio调用在Gtk主循环中运行

har*_*k92 10 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()
Run Code Online (Sandbox Code Playgroud)

编辑:

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

use*_*342 10

gbulb旨在提供PEP 3156指定的asyncio事件循环与GLib主循环实现之间的连接器.但是,当前的master gbulb已经打破了Python 3.4附带的asyncio.要解决此问题,您可以检查此fork而不是master.(问题后来在上游得到修复.)

使用工作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()
Run Code Online (Sandbox Code Playgroud)

另一种可能性是在不同的线程中运行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()
Run Code Online (Sandbox Code Playgroud)

这具有根本不需要的优点gbulb(不清楚gbulb在生产中如何测试良好).但是,需要注意使用线程安全函数在GUI(主)线程和asyncio线程之间进行通信.这意味着使用loop.call_soon_threadsafeasyncio.run_coroutine_threadsafe从GTK向asyncio提交内容,并GLib.idle_add从asyncio向GTK提交内容.