RxIter
RxIter brings observables to python in a bare bones way by using async generators and the async await syntax. In this paradigm observables are analogous to async iterables, and observers analogous to async iterators.
It implements 2 fundamental observable operations, which may be familar to those who know rxpy.
Operations
Share
share allows multiple "observers" to subscribe the same observable
import asyncio
from rxiter import share
async def main():
@share
async def count(): # a counting "observable"
v = 0
while True:
print(f"returning value {v}")
yield v
await asyncio.sleep(1)
v += 1
async def count_squared(obs): # a counting "observer"
async for v in obs:
print(f"{v} squared is {v**2}")
square_task_subscription = asyncio.Task(count_squared(count())) # subscribe
async def count_cubed(obs): # another counting "observer
async for v in obs:
print(f"{v} cubed is {v**3}")
cube_task_subscription = asyncio.Task(count_cubed(count())) # subscribe
await asyncio.gather(square_task_subscription, cube_task_subscription)
asyncio.run(main())
The output on this code would be:
returning value 0
0 squared is 0
0 cubed is 0
returning value 1
1 squared is 1
1 cubed is 1
returning value 2
2 squared is 4
2 cubed is 8
etc...
Repeat
repeat takes a iterator, and "records" it's outputed values so that it is turned into an iterable, and can be "listened" back multiple times.
Example
Polling an API
Suppose we have a API endpoint that we would like to poll to get the most up to date weather in Toronto. We could set up an observable as follows:
async get_toronto_weather():
while True:
yield await poll_my_api("api_enpoint")
await asyncio.sleep(60 * 30) # wait 30 minutes
If you want to "pipe" this to do further operations, like extract some specific content from the dict returned by get_toronto_weather()
async get_temperature():
async for v in poll_api():
yield v["temperature"]
Now if we want to have multiple listeners, that is where the share comes into the picture. We can do
@share
async get_toronto_weather():
while True:
yield await poll_my_api("api_enpoint")
await asyncio.sleep(60 * 30) # wait 30 minutes
async get_temperature():
async for v in get_toronto_weather():
yield v["temperature"]
async get_humidity():
async for v in get_toronto_weather():
yield v["humidity"]
asyncio.Task(get_temperature())
asyncio.Task(get_humidity())
and get_toronto_weather() will only run once for both get_temperature() and get_humidity()
Realtime stdout on python subprocess
Installation
pip install rxiter
Release files for rxiter 0.0.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rxiter-0.0.7.tar.gz | 3.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rxiter-0.0.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 7.3 kB
Release files / rxiter-0.0.7.tar.gz
| Download URL | rxiter-0.0.7.tar.gz |
|---|---|
| Size | 3.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bb1aecd0f6c32c4d86425a5c2c0a362adc65d7da0a270a21b67e3adef7688107
|
|
BLAKE2b-256 checksum How to use checksums |
47c9f1ed2c90623cf98716b7f9542bcfc7a0c2be4843c072d3fe90b42f8a3f5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.9.13
|
Release files / rxiter-0.0.7-py3-none-any.whl
| Download URL | rxiter-0.0.7-py3-none-any.whl |
|---|---|
| Size | 3.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
49bc9b72db9eeb73f379daedd29ab82058bf3e27ab6584bdb8862d6cc5d47be3
|
|
BLAKE2b-256 checksum How to use checksums |
83cd4251ad849d0628241610d3be26797ea3cec40d5f026aabeb434c1abb6b09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.9.13
|