Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3.11: DeprecationWarning: There is no current event loop #757

Closed
ErikvdVen opened this issue Jan 18, 2024 · 16 comments · Fixed by #779
Closed

Python 3.11: DeprecationWarning: There is no current event loop #757

ErikvdVen opened this issue Jan 18, 2024 · 16 comments · Fixed by #779
Labels
Milestone

Comments

@ErikvdVen
Copy link

When running the test suite on Python 3.11, tests with a @pytest.mark.asyncio decorator, trigger a DeprecationWarning:

.../python3.11/site-packages/pytest_asyncio/plugin.py:884: DeprecationWarning: There is no current event loop
   _loop = asyncio.get_event_loop()
@seifertm seifertm added the bug label Jan 28, 2024
@seifertm seifertm modified the milestones: v1.0, v0.23 Jan 28, 2024
@seifertm seifertm added needsinfo Requires additional information from the issue author and removed bug labels Jan 28, 2024
@seifertm
Copy link
Contributor

Which version of pytest-asyncio are you using?
Can you provide a small example that reproduces the issue?

@CherrySuryp
Copy link

CherrySuryp commented Jan 30, 2024

Hi! I encountered same issue

Versions:

  1. python 3.12
  2. pytest-asyncio 0.23.4

Here's traceback

  /python3.12/site-packages/pytest_asyncio/plugin.py:656: DeprecationWarning: There is no current event loop
    old_loop = asyncio.get_event_loop()

@asl97
Copy link

asl97 commented Feb 1, 2024

I think this only happens on the older version of python?

After upgrading from python 3.11.0rc1 to 3.11.7, the warning no longer shows up.
It also doesn't show up on 3.12.1 for me.

platform win32 -- Python 3.11.7, pytest-7.4.4, pluggy-1.4.0
platform win32 -- Python 3.12.1, pytest-7.4.4, pluggy-1.4.0
plugins: asyncio-0.23.4
asyncio: mode=Mode.STRICT

The warning did shows up on older version of python before I updated it.

Which version of pytest-asyncio are you using?

platform win32 -- Python 3.11.0rc1, pytest-7.4.4, pluggy-1.4.0
plugins: asyncio-0.23.4
asyncio: mode=Mode.STRICT

Can you provide a small example that reproduces the issue?

import pytest

@pytest.mark.asyncio
async def test():
    pass

The docs has a footnote on the warning, so it would probably only show up on 3.10.0–3.10.8 and 3.11.0:
https://docs.python.org/3.11/library/asyncio-eventloop.html#asyncio.get_event_loop

Note In Python versions 3.10.0–3.10.8 and 3.11.0 this function (and other functions which use it implicitly) emitted a DeprecationWarning if there was no running event loop, even if the current loop was set on the policy. In Python versions 3.10.9, 3.11.1 and 3.12 they emit a DeprecationWarning if there is no running event loop and no current loop is set. In some future Python release this will become an error.

@seifertm seifertm added bug and removed needsinfo Requires additional information from the issue author labels Feb 6, 2024
@michaljelonek
Copy link

When using asyncio_mode = auto I still see DeprecationWarning on Python 3.12.1, regardless whether the marker decorator is present or not. Switching to strict does resolve it, but that is not something I'd like to do, since none of our tests or fixtures are decorated. Is there something I'm missing that needs to be done when using auto mode to avoid this? Seeing that Python documentation states that in future versions this warning might become an error that is not something I'd like to ignore.

I used the same test that @asl97 provided above.

platform linux -- Python 3.12.1, pytest-7.4.4, pluggy-1.4.0
plugins: asyncio-0.23.4
asyncio: mode=Mode.AUTO
collected 1 item

tests/test_deprecation_warning.py::test PASSED                                                                                                                                                                                     [100%]

============================================================================================================ warnings summary ============================================================================================================
tests/test_deprecation_warning.py::test
  /opt/app-root/venv/lib/python3.12/site-packages/pytest_asyncio/plugin.py:656: DeprecationWarning: There is no current event loop
    old_loop = asyncio.get_event_loop()

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

@ingwinlu
Copy link

ingwinlu commented Feb 8, 2024

I also still see it with 3.12.1 and strict mode:

pytest==8.0.0
pytest-asyncio==0.23.5a0

the warning no longer shows up when i remove my async fixture however that I use to init my database:

@pytest_asyncio.fixture(scope="session", autouse=True)
async def init_db(patch_get_settings):
    from ops_center.persistence import engine

    async with engine.begin() as conn:
        await conn.run_sync(SQLModel.metadata.create_all)

    yield

Alternatively the warning also disappears once I no longer specify:

@pytest.fixture(scope="session")
def event_loop_policy():
    return uvloop.EventLoopPolicy()

@seifertm
Copy link
Contributor

seifertm commented Feb 9, 2024

Pytest-asyncio still uses asyncio.get_event_loop(). The DeprecationWarning could be triggered by the first asyncio test in a test suite. The warning was silenced in pytest-asyncio-0.23.5, so that it doesn't affect user code.

@AivanF
Copy link

AivanF commented Feb 14, 2024

Just tried out the latest, unfortunately, seems like the problem still persists:

===================================================== test session starts ======================================================
platform darwin -- Python 3.10.7, pytest-7.4.3, pluggy-1.0.0
Using --randomly-seed=724078419
rootdir: /Users/aivanf/MyProject
configfile: pyproject.toml
plugins: asyncio-0.23.5, cov-4.1.0, anyio-4.1.0
asyncio: mode=auto
collected 10 items                                                                                                             

tests/test_mycode.py ......                                                                              [ 80%]

======================================================= warnings summary =======================================================
tests/test_mycode.py::test_functions
  /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pytest_asyncio/plugin.py:904: DeprecationWarning: There is no current event loop
    _loop = asyncio.get_event_loop()

@seifertm seifertm reopened this Feb 28, 2024
@graingert
Copy link
Member

@AivanF could this be an interaction with anyio (do you have @pytest.mark.anyio ?) or any calls to asyncio.run?

@binaryDiv
Copy link

binaryDiv commented Mar 5, 2024

We have the same problem in our project.

platform linux -- Python 3.10.6, pytest-8.1.0, pluggy-1.4.0
rootdir: /app
configfile: pytest.ini
plugins: asyncio-0.23.5, requests-mock-1.11.0, cov-4.1.0
asyncio: mode=strict

[...]


self = <Coroutine test_async_foo>

    def runtest(self) -> None:
        self.obj = wrap_in_sync(
            # https://github.com/pytest-dev/pytest-asyncio/issues/596
            self.obj,  # type: ignore[has-type]
        )
>       super().runtest()

/usr/local/lib/python3.10/dist-packages/pytest_asyncio/plugin.py:440: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = (), kwargs = {}, coro = <coroutine object test_async_foo at 0x7537939a0c80>

    @functools.wraps(func)
    def inner(*args, **kwargs):
        coro = func(*args, **kwargs)
>       _loop = asyncio.get_event_loop()
E       DeprecationWarning: There is no current event loop

/usr/local/lib/python3.10/dist-packages/pytest_asyncio/plugin.py:904: DeprecationWarning

The test function looks like this (minimal test that doesn't use anything from the rest of the project):

@pytest.mark.asyncio
async def test_async_foo():
    async def foo():
        return 42

    assert await foo() == 42

@asl97
Copy link

asl97 commented Mar 6, 2024

@AivanF @binaryDiv both your versions are older than 3.10.9.

@seifertm should this issue remain open just for issue on older python version which explicitly mentions would give an warning in the docs, and which would probably go away as soon as they update to a newer 3.10?

@seifertm
Copy link
Contributor

seifertm commented Mar 8, 2024

@asl97 Excellent question

The way the deprecation of asyncio.get_event_loop was handled is unfortunate, because the function is deprecated in some patch releases and not deprecated in others. However, get_event_loop is definitely deprecated in 3.12 and beyond.

The stack trace suggests that the line 904 of the following function triggers the warning:

@functools.wraps(func)
def inner(*args, **kwargs):
coro = func(*args, **kwargs)
_loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coro, loop=_loop)
try:
_loop.run_until_complete(task)
except BaseException:
# run_until_complete doesn't get the result from exceptions
# that are not subclasses of `Exception`. Consume all
# exceptions to prevent asyncio's warning from logging.
if task.done() and not task.cancelled():
task.exception()
raise

This is the reason why I reopened the issue.

Until pytest-asyncio moves away from the use of asyncio.get_event_loop(), which requires breaking changes, all such call from pytest-asyncio to get_event_loop should ignore the warning as in the following example:

try:
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
old_loop = asyncio.get_event_loop()
except RuntimeError:
old_loop = None

I'd be grateful to anyone who contributes a patch with an accompanying regression test added to the test suite.

If I recall correctly, there are a number of places where get_event_loop is called with the pattern illustrated in the lattes example. In that case, it would be even better if the patch deduplicated the code by extracting the above snippet to a dedicated function.

@boholder
Copy link

boholder commented Mar 15, 2024

FYI: Currently you can suppress this warning with pytest filterwarnings option as a workaround:

# in pyproject.toml, or you can configure it in pytest.ini
[tool.pytest.ini_options]
filterwarnings = [
    # This's triggered by pytest-asyncio,
    # which calls deprecated asyncio.get_event_loop() method
    # ref: https://github.com/pytest-dev/pytest-asyncio/issues/757
    "ignore:There is no current event loop",
]

This workaround suits me since I'll never manually create an event loop in my program, thus the option will not blindly suppress warnings generated from my code.

@seifertm
Copy link
Contributor

Pytest-asyncio v0.23.7 has been released. It includes a patch contributed by @SyntaxColoring which should resolve the issue, even with specific CPython patch versions.

@algebraist
Copy link

FWIW, upgrading to pytest-asyncio v0.23.7 did not work for me. I am running Python 3.12.3

@seifertm
Copy link
Contributor

@algebraist Can you provide a minimal reproducer, so we can verify if this and your issue have the same cause?

@algebraist
Copy link

@algebraist Can you provide a minimal reproducer, so we can verify if this and your issue have the same cause?

@seifertm I think my issue may be different actually. I trigger the deprecation warning when I have a single line in a python script:

import ib_async

I was running pytest on files that were importing ib_async, and that was likely triggering the deprecation. The ib_async maintainers are aware of my issue. Thanks for responding!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.