# Adding a low level wait for file descriptor

**URL:** <https://discuss.python.org/t/adding-a-low-level-wait-for-file-descriptor/51442>\
**Category:** Ideas\
**Tags:** asyncio\
**Created:** [April 20, 2024, 4:46am UTC](https://discuss.python.org/t/adding-a-low-level-wait-for-file-descriptor/51442 "2024-04-20T04:46:08Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![pcauchon](https://avatars.discourse-cdn.com/v4/letter/p/898d66/32.png) [@pcauchon](https://discuss.python.org/u/pcauchon)\
**Post date:** [April 20, 2024, 4:46am UTC](https://discuss.python.org/t/adding-a-low-level-wait-for-file-descriptor/51442/1 "2024-04-20T04:46:09Z")

</div>

I had to integrate using asyncio a blocking library that uses sockets.

Typical use case:

```python
async def handler(fd):
    loop = asyncio.get_running_loop()
    while True:
        await loop.wait_readable(fd)
        x = blocking_read_in_library()
        await long_processing(x)

```

I ended up using the `loop.add_reader` and `loop.remove_reader` functions, which is the only approach that seems to work with file descriptors. It’s a bit more error prone but works well. I don’t want to have repeated call to the blocking read if more data is available as anyway the long\_processing happens in the background.

I believe that we could add these two functions instead:

```python
async def wait_readable(loop, fd):
    event = asyncio.Event()
    loop.add_reader(fd, lambda: event.set())

    try:
        await event.wait()

    finally:
        loop.remove_reader(fd)

```

The function `wait_writable` could be implemented similarly. These are very simple functions to implement (maybe they shouldn’t be in stdlib) but I felt they could be useful for others.

---

<div class="post-metadata">

**Author:** ![kalvdans](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/kalvdans/32/4863_2.png) [@kalvdans](https://discuss.python.org/u/kalvdans)\
**Post date:** [February 8, 2026, 8:45am UTC](https://discuss.python.org/t/adding-a-low-level-wait-for-file-descriptor/51442/2 "2026-02-08T08:45:07Z")

</div>

I’d like to see one as well. Right now I have the rather ugly workaround:

```python
async def wait_until_readable(sock, timeout=1e6):
    """Wait until socket is readable, but at most timeout seconds.
    Returns False on timeout, else True."""
    loop = asyncio.get_running_loop()
    future = loop.create_future()

    def callback():
        if not future.cancelled():
            future.set_result(None)

    loop.add_reader(sock, callback)
    try:
        try:
            await asyncio.wait_for(future, timeout=timeout)
        finally:
            loop.remove_reader(sock)
    except asyncio.TimeoutError:
        pass
    return future.done()

```

---

<div class="post-metadata">

**Author:** ![GalaxySnail](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/galaxysnail/32/5655_2.png) [@GalaxySnail](https://discuss.python.org/u/GalaxySnail)\
**Post date:** [February 12, 2026, 5:04am UTC](https://discuss.python.org/t/adding-a-low-level-wait-for-file-descriptor/51442/3 "2026-02-12T05:04:23Z")

</div>

may be related to [Proposal: Adopt proven anyio/Trio patterns natively into asyncio (multi-release roadmap)](https://discuss.python.org/t/proposal-adopt-proven-anyio-trio-patterns-natively-into-asyncio-multi-release-roadmap/106067)

Both trio and anyio support `wait_readable` and `wait_writable`:

[1] [Introspecting and extending Trio with trio.lowlevel — Trio 0.32.0+dev documentation](https://trio.readthedocs.io/en/latest/reference-lowlevel.html#low-level-i-o-primitives)  
[2] [API reference — AnyIO 4.12.0.post14 documentation](https://anyio.readthedocs.io/en/latest/api.html#anyio.wait_readable)
