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()
答案 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_threadsafe
或asyncio.run_coroutine_threadsafe
从GTK向asyncio提交内容,并GLib.idle_add
从asyncio向GTK提交内容。