Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asyncio calls running in Gtk main loop

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()

EDIT:

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.

like image 521
harisk92 Avatar asked Oct 31 '14 12:10

harisk92


1 Answers

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 gbulb is broken for asyncio as shipped with Python 3.4. To fix this, you can check out this fork instead of the master. (The problem was later fixed upstream.)

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.

like image 175
user4815162342 Avatar answered Sep 18 '22 08:09

user4815162342