Git Product home page Git Product logo

asyncio-glib's Introduction

GLib event loop integration for asyncio

This module provides a Python 3 asyncio event loop implementation that makes use of the GLib event loop. This allows for mixing of asyncio and some GLib based code within the same thread.

Enabling this event loop can be achieved with the following code:

import asyncio
import asyncio_glib
asyncio.set_event_loop_policy(asyncio_glib.GLibEventLoopPolicy())

At this point, asyncio.get_event_loop() will return a GLibEventLoop.

Implementation strategy

To ease maintenance, I have tried to reuse as much of the standard library asyncio code as possible. To this end, I created a GLib implementation of the selectors.BaseSelector API. Combine this with the existing asyncio.SelectorEventLoop class, and we have our event loop implementation.

To test that the event loop is functional, I have reused parts of the standard library test suite to run against the new selector and event loop.

At present the selector sublcasses the private selectors._BaseSelectorImpl class, which is a potential source of future compatibility problems. If that happens, taking a local copy of that code is an option.

Comparison with Gbulb

Gbulb is another implementation of the asyncio event loop on top of GLib. The main differences are:

  • Gbulb dispatches asyncio callbacks directly from the GLib main loop. In contrast, asyncio-glib iterates the GLib main loop until an asyncio event is ready and then has asyncio event loop dispatch the event.

  • Gbulb has some Windows compatibility code, while asyncio-glib has had no testing on that platform.

  • asyncio-glib is an essentially unmodified SelectorEventLoop, so should automatically gain any features from new Python releases.

The asyncio-glib code base is also about one tenth of the size of Gbulb.

asyncio-glib's People

Contributors

jhenstridge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

asyncio-glib's Issues

Using GLibEventLoop on Python 3.8 causes assertion: not instance of AbstractEventLoopPolicy

Traceback (most recent call last):
  File "app.py", line 11, in <module>
    asyncio.set_event_loop_policy(asyncio_glib.GLibEventLoop())
  File "/usr/lib64/python3.8/asyncio/events.py", line 731, in set_event_loop_policy
    assert policy is None or isinstance(policy, AbstractEventLoopPolicy)
AssertionError
Exception ignored in: <function BaseEventLoop.__del__ at 0x7fe1607db3a0>
Traceback (most recent call last):
  File "/usr/lib64/python3.8/asyncio/base_events.py", line 652, in __del__
  File "/usr/lib64/python3.8/asyncio/unix_events.py", line 58, in close
  File "/usr/lib64/python3.8/asyncio/selector_events.py", line 92, in close
  File "/usr/lib64/python3.8/asyncio/selector_events.py", line 99, in _close_self_pipe
  File "/usr/lib64/python3.8/asyncio/selector_events.py", line 281, in _remove_reader
  File "/home/clayton/repos/app/venv/lib/python3.8/site-packages/asyncio_glib/glib_selector.py", line 88, in unregister
  File "/home/clayton/repos/app/venv/lib/python3.8/site-packages/asyncio_glib/glib_selector.py", line 59, in unregister

Can be reproduced with this on python 3.8:

import asyncio
import asyncio_glib


async def main():
    print('good bye world')
    await asyncio.sleep(42)


asyncio.set_event_loop_policy(asyncio_glib.GLibEventLoop())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Callback is never called when set_result() is called on a Future

When code triggered by a Gtk signal calls set_result() on an asyncio Future object, it seems the callbacks on the Future object are not called unless something else wakes up the main loop.

I've put together the following minimal example of this bug.

Expected behaviour: clicking the button should print, 'button clicked' and 'future finished', then the main loop should end.
Actual behaviour: clicking the button prints 'button clicked', then the main loop continues forever.
Tested with: Python 3.6.9, Gtk 3.22.30 and asyncio-glib 0.1.

If you uncomment the heartbeat line, so that there's a regular timed call happening, then the Future's callback is called and the main loop ends. But with that line commented, the loop does not end.

import asyncio
import asyncio_glib
from gi.repository import Gtk

asyncio.set_event_loop_policy(asyncio_glib.GLibEventLoopPolicy())


class Demo:
    def __init__(self):
        self.future = asyncio.get_event_loop().create_future()

        self.window = Gtk.Window()
        button = Gtk.Button.new_with_label('Click here')
        button.connect('clicked', self.button_clicked)
        self.window.add(button)
        self.window.show_all()

    def button_clicked(self, widget):
        print('button clicked')
        self.window.close()
        self.future.set_result(None)


async def main():
    # Uncomment the following line and everything works.
    # asyncio.get_event_loop().call_later(1, heartbeat)
    demo = Demo()
    await demo.future
    print('future finished')


def heartbeat():
    asyncio.get_event_loop().call_later(1, heartbeat)
    print('tick')


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())

Asyncio subprocess EOF is never received

When running a subprocess using asyncio-glib and having stdout as a PIPE, the EOF is never received. This happens because the selector doesn't listen for the GLib HUP signal.

A minimal non-working example:

import asyncio
from asyncio import subprocess

from asyncio_glib import GLibEventLoopPolicy


async def main():
    proc = await asyncio.create_subprocess_exec('ls', '-la', '/tmp', stdout=subprocess.PIPE)

    async for line in proc.stdout:
        print(line)

    print('DONE')

if __name__ == '__main__':
    asyncio.set_event_loop_policy(GLibEventLoopPolicy())
    asyncio.run(main())

The print('DONE') line is never reached. When running this wihtout the GLibEventLoopPolicy, it does work.

Gstreamer Example

Hi

Do you have a gstreamer Example?
I want to use asyncio websocketes to emit Data on a gatreamer callback. Is that possible with your project? Big thanks

BR

GTK example

Could you include an example of how you would use this with a GTK application?

For example, convert the below program into asyncio, while replacing the time.sleep() with an await so that the window still runs until the timeout:

import time
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk

class Application(Gtk.Application):
    def do_activate(self):
        self.window = Gtk.ApplicationWindow(application=self)
        spinner = Gtk.Spinner()
        label = Gtk.Label("Done")

        self.window.set_default_size(320, 320)
        self.window.add(spinner)
        self.window.show_all()

        spinner.start()
        time.sleep(10)
        self.window.remove(spinner)
        self.window.add(label)
        self.window.show_all()

app = Application()
app.run()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.