Coder Social home page Coder Social logo

Comments (5)

graingert avatar graingert commented on May 24, 2024 1

@seifertm currently I'm trying to remove the policy system and get/set event loop in favour of loop_factory so this becomes a non-issue.

I think to fix this instead of using _provide_clean_event_loop you should call set_event_loop_policy(None) so asyncio.get_event_loop() returns to its original behaviour

from pytest-asyncio.

graingert avatar graingert commented on May 24, 2024

full demo here kevin1024/vcrpy@d009336

more minimal reproducer here https://github.com/graingert/asyncio_unclosed_loop

from pytest-asyncio.

graingert avatar graingert commented on May 24, 2024

I repeated this with e1415c1

from pytest-asyncio.

phillipuniverse avatar phillipuniverse commented on May 24, 2024

I have the same issue in versions 0.22.0+, including 0.23.0a0.

I first spent a ton of time trying to hunt down a new ResourceWarning I seemingly randomly started getting in my tests (maybe due to the more tests I added and thus more time to fail with the resource warning, unsure):

>               warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
E               pytest.PytestUnraisableExceptionWarning: Exception ignored in: <socket.socket fd=-1, family=1, type=1, proto=0>
E               
E               Traceback (most recent call last):
E                 File "/Users/phillip/.pyenv/versions/3.11.6/lib/python3.11/json/decoder.py", line 353, in raw_decode
E                   obj, end = self.scan_once(s, idx)
E                              ^^^^^^^^^^^^^^^^^^^^^^
E               ResourceWarning: unclosed <socket.socket fd=13, family=1, type=1, proto=0>

I couldn't for the life of me figure out where I had an unclosed socket. So I finally admitted defeat and silenced the ResourceWarning, only to have this next error happen:

>               warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
E               pytest.PytestUnraisableExceptionWarning: Exception ignored in: <function BaseEventLoop.__del__ at 0x104bed760>
E               
E               Traceback (most recent call last):
E                 File "/Users/phillip/.pyenv/versions/3.11.6/lib/python3.11/asyncio/base_events.py", line 692, in __del__
E                   _warn(f"unclosed event loop {self!r}", ResourceWarning, source=self)
E               ResourceWarning: unclosed event loop <_UnixSelectorEventLoop running=False closed=False debug=False>

The results seemed to change depending on how many tests I was running in my test suite.

Downgrading to 0.21.1 fixed both problems.

from pytest-asyncio.

seifertm avatar seifertm commented on May 24, 2024

Thanks for the report! I can reproduce the issue with pytest-asyncio v0.23.2. I can also reproduce it with pytest-asyncio v0.21.1, though:

$ python -X dev -m pytest --setup-show
===== test session starts =====
platform linux -- Python 3.12.1, pytest-7.4.3, pluggy-1.3.0
rootdir: /tmp/tst
plugins: asyncio-0.21.1
asyncio: mode=Mode.STRICT
collected 2 items                                                                                                                   

test_a.py 
        SETUP    F event_loop
        SETUP    F demo (fixtures used: event_loop)
        test_a.py::test_aiohttp_test_client_json (fixtures used: demo, event_loop, request).
        TEARDOWN F demo
        TEARDOWN F event_loop
        test_a.py::test_redirect.

===== warnings summary =====test_a.py::test_redirect
  /usr/lib/python3.12/asyncio/base_events.py:723: ResourceWarning: unclosed event loop <_UnixSelectorEventLoop running=False closed=False debug=True>
    _warn(f"unclosed event loop {self!r}", ResourceWarning, source=self)
  Enable tracemalloc to get traceback where the object was allocated.
  See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info.

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
===== 2 passed, 1 warning in 0.02s =====

This means it's probably not directly related to the v0.23 release.

Based on the console output above, my current understanding is that pytest(-asyncio) runs the async test normally. When the event_loop fixture is torn down, a fixture finalizer creates a new event loop to prevent subsequent non-async tests from having to deal with a closed loop:

def _provide_clean_event_loop() -> None:
# At this point, the event loop for the current thread is closed.
# When a user calls asyncio.get_event_loop(), they will get a closed loop.
# In order to avoid this side effect from pytest-asyncio, we need to replace
# the current loop with a fresh one.
# Note that we cannot set the loop to None, because get_event_loop only creates
# a new loop, when set_event_loop has not been called.
policy = asyncio.get_event_loop_policy()
new_loop = policy.new_event_loop()
policy.set_event_loop(new_loop)

When the sync test calls asyncio.run, the loop created by the fixture finalizer is not closed by the asyncio Runner. I very recently encountered the same problem in a different issue.

@graingert I'm aware you're involved in upstream asyncio development. Do you think it's worth filing an enhancement issue for asyncio.run (or rather asyncio.Runner) to close any existing loop before setting a new loop?

@phillipuniverse If you don't use asyncio.run, it's possible that your issue has a separate cause. I can help more, if you provide a reproducer for you specific issue.

from pytest-asyncio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.