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

RuntimeError: Cannot run the event loop while another loop is running #359

Closed
baiyyee opened this issue May 25, 2022 · 6 comments
Closed

Comments

@baiyyee
Copy link

baiyyee commented May 25, 2022

When trying to do UI automtion with pytest-asyncio and pytest-playwright, I got exception like: RuntimeError: Cannot run the event loop while another loop is running

Code structure:

ui2/conftest.py
ui2/test_bing.py

ui2/conftest.py

import pytest
import asyncio


@pytest.fixture(scope="session")
def event_loop():
    """重写event_loop"""

    loop = asyncio.get_event_loop()
    yield loop
    loop.close()

ui2/test_bing.py

import pytest

from playwright.async_api import Page


@pytest.mark.asyncio
async def test_bing(page: Page):
    await page.goto("http://www.bing.com")

env:

pytest==7.1.2
pytest-asyncio==0.18.3
pytest-playwright==0.3.0

Detail exception as below:

image

@seifertm
Copy link
Contributor

seifertm commented Jun 4, 2022

Thank you for the report and the example. Unfortunately, I will not have time to look into this for the next two weeks. If nobody else is going to pick this up, it'll have to wait until then.

@PeterStolz
Copy link

Hi, I also encountered a similar problem.
To give you a minimal proof of concept in python3.10:
runner.py

import pytest                                                                                                   
import asyncio                                                                                                  
                 
# using nest_asyncio mitigates the problem                                                                                               
#import nest_asyncio                                                                                            
#nest_asyncio.apply()                                                                                                      
                                                                                                                
async def runner():                                                                                             
    pytest.main(['-k', 'test_asdf', 'test_file.py'])                                                            
                                                                                                                
loop = asyncio.get_event_loop()                                                                                 
loop.run_until_complete(runner())                                                                               
           
# does not raise an exception                                                                                                                                                                                                                     
# pytest.main(['-k', 'test_asdf', 'test_file.py'])     

test_file.py

import pytest                                                                                                   
                                                                                                                
@pytest.mark.asyncio                                                                                            
async def test_asdf():                                                                                          
    assert True     
Executing the runner yields the same stacktrace:

/home/peter/Documents/pytestbug/test_runner.py:14: DeprecationWarning: There is no current event loop
  loop = asyncio.get_event_loop()
============================================= test session starts ==============================================
platform linux -- Python 3.10.4, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/peter/Documents/pytestbug
plugins: asyncio-0.18.4.dev36+gc021932.d20220609
asyncio: mode=legacy
collected 1 item                                                                                               

test_file.py F                                                                                           [100%]

=================================================== FAILURES ===================================================
__________________________________________________ test_asdf ___________________________________________________

args = (), kwargs = {}, coro = <coroutine object test_asdf at 0x7f7c47cb3300>
old_loop = <_UnixSelectorEventLoop running=False closed=False debug=False>
task = <Task pending name='Task-2' coro=<test_asdf() running at /home/peter/Documents/pytestbug/test_file.py:5>>

    @functools.wraps(func)
    def inner(*args, **kwargs):
        coro = func(*args, **kwargs)
        if not inspect.isawaitable(coro):
            pyfuncitem.warn(
                pytest.PytestWarning(
                    f"The test {pyfuncitem} is marked with '@pytest.mark.asyncio' "
                    "but it is not an async function. "
                    "Please remove asyncio marker. "
                    "If the test is not marked explicitly, "
                    "check for global markers applied via 'pytestmark'."
                )
            )
            return
        nonlocal _loop
        _loop.stop()
        old_loop = _loop
        # old_loop
        _loop = asyncio.new_event_loop()
        asyncio.set_event_loop(_loop)
        task = asyncio.ensure_future(coro, loop=_loop)
        try:
>           _loop.run_until_complete(task)

../../.virtualenvs/pytestbug/lib/python3.10/site-packages/pytest_asyncio/plugin.py:460: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3.10/asyncio/base_events.py:622: in run_until_complete
    self._check_running()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_UnixSelectorEventLoop running=False closed=False debug=False>

    def _check_running(self):
        if self.is_running():
            raise RuntimeError('This event loop is already running')
        if events._get_running_loop() is not None:
>           raise RuntimeError(
                'Cannot run the event loop while another loop is running')
E           RuntimeError: Cannot run the event loop while another loop is running

/usr/lib/python3.10/asyncio/base_events.py:584: RuntimeError
=============================================== warnings summary ===============================================
../../.virtualenvs/pytestbug/lib/python3.10/site-packages/pytest_asyncio/plugin.py:191
  /home/peter/.virtualenvs/pytestbug/lib/python3.10/site-packages/pytest_asyncio/plugin.py:191: DeprecationWarning: The 'asyncio_mode' default value will change to 'strict' in future, please explicitly use 'asyncio_mode=strict' or 'asyncio_mode=auto' in pytest configuration file.
    config.issue_config_time_warning(LEGACY_MODE, stacklevel=2)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================== short test summary info ============================================
FAILED test_file.py::test_asdf - RuntimeError: Cannot run the event loop while another loop is running
========================================= 1 failed, 1 warning in 0.10s =========================================
/usr/lib/python3.10/asyncio/base_events.py:685: ResourceWarning: unclosed event loop <_UnixSelectorEventLoop running=False closed=False debug=False>
sys:1: RuntimeWarning: coroutine 'test_asdf' was never awaited
Task was destroyed but it is pending!
task: <Task pending name='Task-2' coro=<test_asdf() running at /home/peter/Documents/pytestbug/test_file.py:5>>

The problem is that there is an existing event loop that is already running and I suspect that is happening on @SilenceHe 's imported code

This can be mitigated by using nest_asyncio.

I tried other solutions but unfortunately it seems like using nest_asyncio is the best option.

@graingert
Copy link
Member

one issue here is that you're expecting an async_api.Page, but pytest-playright uses the sync_api.Page https://github.com/microsoft/playwright-pytest/blob/456f8286f09f132d2e21f6bf71f27465e71ba17a/pytest_playwright/pytest_playwright.py#L22

import pytest

from playwright.async_api import Page


@pytest.mark.asyncio
async def test_bing(page: Page):
    await page.goto("http://www.bing.com/")

@seifertm
Copy link
Contributor

@graingert Thanks for jumping in!

As mentioned playwright-pytest only supports the synchronous Playwright API at the moment (see microsoft/playwright-pytest#74).

@SilenceHe This comment in particular state that only playwright.sync_api is supported by playwright-pytest and links to a conftest.py that allows the asynchronous API to be used.

@seifertm
Copy link
Contributor

I didn't know about nest_asyncio. The project seems to solve the same problem as https://github.com/aio-libs/aioloop-proxy for which a draft PR exists (#312).

@PeterStolz Your error message is similar to that of the OP. I see your problem as a different one, though, because it has nothing to do with playwright-pytest. Do you mind opening a separate issue for your? It would be very helpful if you could explain your use case a bit more.

CC @asvetlov It seems that nest_asyncio and aioloop-proxy do pretty much the same.

@seifertm
Copy link
Contributor

Closing this issue as this doesn't seem to be a pytest-asyncio bug. Feel free to reopen, especially if there is anything we can do to improve support for playwright-pytest.

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

No branches or pull requests

4 participants