On Windows, Psycopg is not compatible with the default
`~asyncio.ProactorEventLoop`. Please use a different loop, for instance
- the `~asyncio.SelectorEventLoop`.
+ the `~asyncio.SelectorEventLoop`. See `asyncio documentation`__ for details.
- For instance, you can use, early in your program:
-
- .. parsed-literal::
-
- `asyncio.set_event_loop_policy`\ (
- `asyncio.WindowsSelectorEventLoopPolicy`\ ()
- )
+ .. __: https://docs.python.org/3.14/library/asyncio-eventloop.html#asyncio.SelectorEventLoop
else:
from typing_extensions import LiteralString, Self
+if sys.version_info >= (3, 12):
+ _asyncio_run_snippet = (
+ "running 'asyncio.run(...,"
+ " loop_factory=asyncio.SelectorEventLoop(selectors.SelectSelector()))'"
+ )
+
+else:
+ _asyncio_run_snippet = (
+ "setting 'asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())'"
+ )
+
if sys.version_info >= (3, 13):
from typing import TypeVar
else:
if sys.platform == "win32":
loop = asyncio.get_running_loop()
if isinstance(loop, asyncio.ProactorEventLoop):
+
+ from ._compat import _asyncio_run_snippet
+
raise e.InterfaceError(
"Psycopg cannot use the 'ProactorEventLoop' to run in async"
" mode. Please use a compatible event loop, for instance by"
- " setting 'asyncio.set_event_loop_policy"
- "(WindowsSelectorEventLoopPolicy())'"
+ + f" {_asyncio_run_snippet}"
)
params = await cls._get_connection_params(conninfo, **kwargs)
asyncio_options: dict[str, Any] = {}
if sys.platform == "win32":
- asyncio_options["loop_factory"] = (
- asyncio.WindowsSelectorEventLoopPolicy().new_event_loop
+ asyncio_options["loop_factory"] = lambda: asyncio.SelectorEventLoop(
+ selectors.SelectSelector()
)
# These tests relate to AsyncConnectionPool, but are not marked asyncio
# because they rely on the pool initialization outside the asyncio loop.
-import sys
import asyncio
import pytest
+from tests.utils import asyncio_run as asyncio_run_
+
try:
import psycopg_pool as pool
except ImportError:
In certain runs, fd objects are leaked and the error will only be caught
downstream, by some innocent test calling gc_collect().
"""
- if sys.platform == "win32":
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
recwarn.clear()
try:
- yield asyncio.run
+ yield asyncio_run_
finally:
gc_collect()
if recwarn:
import random
import asyncio
import logging
+import selectors
from enum import Enum
from typing import Any
from argparse import ArgumentParser, Namespace
elif name == Driver.psycopg_async:
import psycopg
+ kwargs: dict[str, Any] = {}
if sys.platform == "win32":
- if hasattr(asyncio, "WindowsSelectorEventLoopPolicy"):
+ if sys.version_info >= (3, 12):
+ kwargs["loop_factory"] = lambda: asyncio.SelectorEventLoop(
+ selectors.SelectSelector()
+ )
+ else:
asyncio.set_event_loop_policy(
asyncio.WindowsSelectorEventLoopPolicy()
)
- asyncio.run(run_psycopg_async(psycopg, args))
+ asyncio.run(run_psycopg_async(psycopg, args), **kwargs)
elif name == Driver.asyncpg:
import asyncpg # type: ignore
import sys
import uuid
import asyncio
+import selectors
import psycopg
if __name__ == "__main__":
+ kwargs = {{}}
if sys.platform == "win32":
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+ if sys.version_info >= (3, 12):
+ kwargs["loop_factory"] = lambda: asyncio.SelectorEventLoop(
+ selectors.SelectSelector()
+ )
+ else:
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
try:
- asyncio.run(main())
+ asyncio.run(main(), **kwargs)
finally:
assert excs, "No exception raised by workers"
for ex in excs:
import re
import sys
+import asyncio
import operator
+import selectors
+from typing import Any
from contextlib import contextmanager
from collections.abc import Callable
return conn.set_autocommit(value)
else:
raise TypeError(f"not a connection: {conn}")
+
+
+def windows_loop_factory() -> asyncio.AbstractEventLoop:
+ return asyncio.SelectorEventLoop(selectors.SelectSelector())
+
+
+def asyncio_run(coro: Any, *, debug: bool | None = None) -> Any:
+ # loop policies are deprecated from Python 3.14
+ # loop_factory was introduced in Python 3.12
+ kwargs: dict[str, Any] = {}
+ if sys.platform == "win32":
+ if sys.version_info >= (3, 12):
+ kwargs["loop_factory"] = lambda: asyncio.SelectorEventLoop(
+ selectors.SelectSelector()
+ )
+ else:
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
+ return asyncio.run(coro, debug=debug, **kwargs)