kplindegaard / smbus2

A drop-in replacement for smbus-cffi/smbus-python in pure Python
MIT License
243 stars 68 forks source link

asyncio support in smbus2 #18

Open jabdoa2 opened 6 years ago

jabdoa2 commented 6 years ago

We use smbus2 in the Mission Pinball Framework (https://github.com/missionpinball/mpf/). However, MPF is an asyncio application and most operations will block for a while. It certainly works because I2C is fast but we would like to keep latency down in the app. I looked into non-blocking mode for the smbus interface and i2c on Linux in general but i looks like that either does not work or nobody uses it. So we can probably not use select (or epoll) via the asyncio loop. Let me know if you thing that this would work.

However, I would like to have an asyncio smbus implementation anyway. Would you be up to merge a change where all ioctls would happen in an executor (a separate thread in asyncio) which synchronizes via two queues? That way the asyncio app would not have to block when performing operations and the library would only require minimal changes. What do you think?

kplindegaard commented 6 years ago

Hello and sorry for late response.

It sounds interesting to have an asyncio implementation, so feel free to fork and implement what you need. Couldn't be happier. However, I am inclined to think that an async version is such a large improvement that it is probably better served as a separate library.

jabdoa2 commented 6 years ago

https://github.com/jabdoa2/smbus2_asyncio

miili commented 6 years ago

This async solution should go into the main library!

AlexisTM commented 6 years ago

What are the drawbacks of the Asyncio version? @jabdoa2

kplindegaard commented 6 years ago

As far as I know, asyncio came in Python 3.4, and I would like smbus2 should work for 2.7 as well. There are ways to overcome that of course. PS: Seems I should withdraw parts of my previous comment about large (in terms of code size) improvement. Not very familiar with asyncio as you guys understand.

AlexisTM commented 6 years ago

I am a user of Python 2.7; And indeed, to keep "'drop-in" replacement of smbus, that support should not be dropped.

jabdoa2 commented 6 years ago

@alexistm The current asyncio implementation will probably use slightly more CPU. However, I2C is usually not used to exchange data at very high data rates so it should be fine. I guess that this could also get optimized if it becomes a problem.

jabdoa2 commented 6 years ago

@kplindegaard there are some asyncio backports for 2.7. However, those async functions could exist in addition to the sync functions and would not break backwards compatibility.

kplindegaard commented 6 years ago

@jabdoa2 A very simple merge option is to just import the asyncio class if Python version is 3.4 or higher. For example append this to smbus2.initpy

from platform import python_version_tuple

if python_version_tuple() >= (3, 4):
    from .smbus2_asyncio import SMBus2Asyncio

and just copy your smbus2_asyncio.py right into this repo. I think that should suffice and I would be honered to have it in. But would you be comfortable with that?

uSpike commented 3 years ago

I'd just like to add that it'd be great if an async implementation could utilize anyio so that the project could be reused with asyncio and trio: https://anyio.readthedocs.io/en/stable/