Okey guys question concerning asyncio and Gtk+. How can I run code below in Gtk.main loop ? I searched for example but couldn't find any.
#!/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()
Okey I should write my experiance with gbulb. First I searched it using pip3 . I found it and tried to install it but it failed(I was using super user for installation) due bad links. Next I downloaded it from their repository and installed it .I got this example I run it and got some errors for missing arguments in their core module.I don't know really which error is it cause Iam writing this from different PC I'll update is ASAP. Also I would be grateful if anybody else could test it.
As of 2020, the gbulb library appears to be unmaintained. Anyone wishing to integrate asyncio and GTK should only consider the second part of the answer (showing asyncio running in a dedicated thread) or take a look at asyncio-glib
, which integrates asyncio and GTK using an approach more minimalistic and robust than that taken by gbulb.
Original answer follows below.
The gbulb
library is designed to provide a connector between the asyncio event loop as specified by PEP 3156 and the GLib main loop implementation. However, the current master of (The problem was later fixed upstream.)gbulb
is broken for asyncio as shipped with Python 3.4. To fix this, you can check out this fork instead of the master.
With a working gbulb, it is trivial to modify your example to both accept incoming connections and run GTK:
#!/usr/bin/python3
import gi
gi.require_version("Gtk", "3.0")
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()
Another possibility is to run the asyncio event loop in a different thread:
#!/usr/bin/python3
import asyncio, threading
import gi
gi.require_version("Gtk", "3.0")
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()
This has the advantage of not requiring gbulb
at all (it is not clear how well gbulb
has been tested in production). One does need to be careful, however, to use thread-safe functions to communicate between the GUI (main) thread and the asyncio thread. This means using loop.call_soon_threadsafe
or asyncio.run_coroutine_threadsafe
to submit things to asyncio from GTK, and GLib.idle_add
to submit things to GTK from asyncio.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With