Skip to content

Replace asyncio.set_event_loop_policy() before Python 3.16 removes the policy system #228

@bluet

Description

@bluet

Background

While reviewing #203 / PR #210, I confirmed against the Python 3.14 asyncio-eventloop docs that the asyncio policy system — including `asyncio.set_event_loop_policy()` and `WindowsSelectorEventLoopPolicy` — is scheduled for removal in Python 3.16, not merely deprecated.

Note: The asyncio policy system is deprecated and will be removed in Python 3.16; from there on, this function will return the current running event loop if present else it will return the loop set by `set_event_loop()`.

This is a more aggressive timeline than #203 originally noted (which deferred the change because "the replacement story is messier").

Affected code

```python

proxybroker/cli.py:11-12

if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
```

This module-level statement runs at import time on Windows to force the selector loop (avoiding aiohttp/aiodns issues with the proactor loop on Windows).

Why we did this in the first place

aiohttp / aiodns historically require the selector event loop on Windows; the default proactor loop breaks SSL and DNS in subtle ways. The current code uses the documented override mechanism.

Replacement options to evaluate

  1. Manual loop construction. In Python 3.16+, the policy system is gone. The new pattern is:
    ```python
    if sys.platform == "win32":
    loop = asyncio.SelectorEventLoop()
    asyncio.set_event_loop(loop)
    ```
    But this only sets the loop for the current thread, not the default for new threads.

  2. `asyncio.run()` + custom loop factory. Pass a custom event loop to `asyncio.run()` via the `loop_factory` parameter (added in 3.12+). This is cleaner but requires a broader refactor of `cli.py` to use `asyncio.run()` instead of the manual `new_event_loop` + `set_event_loop` + `run_until_complete` + `close` pattern.

  3. Drop Windows selector override entirely. Modern aiohttp/aiodns may have fixed the proactor compatibility issues — needs verification across the supported Windows + Python matrix.

Acceptance criteria

  • No `asyncio.set_event_loop_policy()` call remains in the codebase
  • CLI works on Windows with Python 3.16+ (when 3.16 ships) without DeprecationWarning or AttributeError
  • CI matrix verifies Windows + Python 3.16 once available
  • Document the chosen approach in CLAUDE.md or contributor docs

Priority

Medium — Python 3.16 lands in ~Oct 2027 per the PEP 596 schedule, so we have ~17 months. But this should be addressed before then to avoid a hard break.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions