Ответ 1
РЕДАКТИРОВАТЬ
По состоянию на 2019 г. библиотека gbulb, по-видимому, не поддерживается. Любой, кто хочет интегрировать Asyncio и GTK, вероятно, должен рассмотреть только вторую часть ответа.
Библиотека gbulb
предназначена для обеспечения связующего звена между циклом событий асинхронности, как указано в PEP 3156, и реализацией основного цикла GLib. Тем не менее, текущий мастер gbulb
работает для asyncio, как поставляется с Python 3.4.Чтобы исправить это, вы можете проверить эту вилку вместо мастера. (Впоследствии проблема была исправлена.)
С работающим 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
для отправки вещей в asyncio из GTK и GLib.idle_add
для отправки вещей в GTK из asyncio.