Skip to content

Latest commit

 

History

History
184 lines (128 loc) · 5.31 KB

File metadata and controls

184 lines (128 loc) · 5.31 KB

Getting Started

This page covers the parts most Python users will touch first.

Requirements

The package metadata requires CPython 3.10+. The repository declares support through 3.15, including 3.14t and 3.15t. The native runtime requires Linux 6.1+, macOS 13+, or Windows 10+. These are source and CI compatibility declarations; they do not establish that a wheel exists for every interpreter and architecture. For source installation, use the pinned Rust toolchain and development instructions.

Install

From PyPI:

pip install rsloop

With uv:

uv add rsloop

From conda-forge, using pixi:

pixi add rsloop

The public API

The package exports a small public surface:

  • rsloop.Loop
  • rsloop.EventLoopPolicy
  • rsloop.__version__
  • rsloop.build_info()
  • rsloop.transport_stats()
  • rsloop.reset_transport_stats()
  • rsloop.new_event_loop()
  • rsloop.run(...)
  • rsloop.install()
  • rsloop.uninstall()

For most programs, rsloop.run(...) is enough. See the API reference for signatures, cleanup, and errors.

Build diagnostics

Use build_info() when reporting an installation or platform-specific issue:

import rsloop


print(rsloop.build_info())

It returns the package version, debug or release profile, target OS and architecture, whether the build interpreter was free-threaded, selected I/O reactor, and TLS backend. The free_threaded diagnostic reports whether this build targets a free-threaded interpreter. rsloop supports free-threaded CPython 3.14 and 3.15 (3.14t, 3.15t) and declares gil_used = false, so importing it does not re-enable the GIL. The exact values depend on the installed wheel or local build.

Simplest way to use it

import rsloop


async def main() -> str:
    return "done"


result = rsloop.run(main())
print(result)

This is similar to asyncio.run(...), but it creates and uses an rsloop loop.

Install as the default asyncio loop

Use install() when you want plain asyncio entry points to create rsloop loops:

import asyncio
import rsloop


async def main() -> None:
    print("hello from rsloop")


rsloop.install()
try:
    asyncio.run(main())
finally:
    rsloop.uninstall()

uninstall() restores the event loop policy that was active before install(), which is useful in tests that switch between loop implementations. If another library has already installed a different policy, uninstall() leaves that newer policy in place.

Manual loop creation

Use manual loop creation when you need more control:

import asyncio
import rsloop


loop = rsloop.new_event_loop()
asyncio.set_event_loop(loop)
try:
    loop.run_until_complete(asyncio.sleep(0))
finally:
    asyncio.set_event_loop(None)
    loop.close()

What still feels like normal asyncio?

A lot of the programming model stays the same. For example:

  • async def coroutines
  • await
  • asyncio.create_task(...)
  • protocols and transports
  • socket helpers such as sock_recv(...)
  • servers and connections
  • subprocess helpers

The big difference is the implementation of the event loop itself.

Import-time behavior

Importing rsloop does a little setup work:

  • it boots the native extension
  • it wraps selected ssl.SSLContext methods to track certificate and trust configuration for the rustls backend
  • it patches asyncio.set_event_loop(...) for compatibility, especially on older Python versions
  • it patches asyncio.open_connection(...) and asyncio.start_server(...) to use native fast streams on rsloop, including TLS
  • it wraps asyncio.create_subprocess_exec(...) and asyncio.create_subprocess_shell(...) to support rsloop text-mode subprocess streams; other loops use the original helpers

Native fast streams are automatic on rsloop, with no mode switch or stdlib fallback. Other event loops retain their standard stream helpers. See Fast Streams for the supported stream interface.

Useful examples

The examples/ directory is the best hands-on tour of the project:

  • examples/01_basics.py: loop lifecycle, callbacks, tasks, executors
  • examples/02_fd_and_sockets.py: file descriptor watchers and socket helpers
  • examples/03_streams.py: TCP protocols, connections, and servers
  • examples/04_unix_and_accepted_socket.py: Unix sockets and accepted sockets
  • examples/05_pipes_signals_subprocesses.py: pipes, signals, and subprocesses
  • examples/fastapi_service.py: a FastAPI service with selectable event loops
  • examples/picows_server.py: a Picows WebSocket server
  • examples/picows_test.py: a Picows client for the example server
  • examples/wsbench_websockets.py: a WebSocket benchmark server
  • examples/rust/: a PyO3 extension that returns Rust-backed awaitables

If you are new to lower-level asyncio features, start with 01_basics.py and 03_streams.py.

There is also a shorter docs page with copy-paste snippets in Examples.

Adding your own async Rust code

If you want to keep using rsloop in Python while exposing your own async Rust functions from a separate PyO3 extension, read Rust Extensions.

That page explains how to turn a Rust future into a Python awaitable with rsloop::rust_async::future_into_py(...).