Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

"RuntimeError: Thread 'MainThread' already has a main context" when used with glib event loop #1233

Open
@marmarek

Description

@marmarek

glib event loop has its own event loop policy, and implicitly sets the event loop for the main thread. Seehttps://pygobject.gnome.org/guide/asynchronous.html
Note this needs gobject >= 3.50.0, to have the native asyncio support.

This doesn't work with pytest-asyncio and results in exception as in title whenpytest_fixture_setup callspolicy.set_event_loop(loop).

Minimal reproducer:

importasyncioimportpytestfromgi.eventsimportGLibEventLoopPolicyasyncio.set_event_loop_policy(GLibEventLoopPolicy())@pytest.mark.asyncioasyncdeftest_foo():pass

The output:

======================================= ERRORS =======================================_____________________________ ERROR at setup of test_foo _____________________________policy = <gi.events.GLibEventLoopPolicy object at 0x7f81069ecc20>    @contextlib.contextmanager    def _temporary_event_loop_policy(policy: AbstractEventLoopPolicy) -> Iterator[None]:        old_loop_policy = _get_event_loop_policy()        try:            old_loop = _get_event_loop_no_warn()        except RuntimeError:            old_loop = None        _set_event_loop_policy(policy)        try:>           yieldusr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:543: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ usr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:757: in _scoped_runner    runner = Runner().__enter__()usr/lib64/python3.14/asyncio/runners.py:59: in __enter__    self._lazy_init()usr/lib64/python3.14/asyncio/runners.py:150: in _lazy_init    events.set_event_loop(self._loop)usr/lib64/python3.14/asyncio/events.py:839: in set_event_loop    _get_event_loop_policy().set_event_loop(loop)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <gi.events.GLibEventLoopPolicy object at 0x7f81069ecc20>loop = <GLibEventLoop running=False closed=False debug=False ctx=0x5FB5B1886F60 loop=0x5FB5B1B968A0>    def set_event_loop(self, loop):        """Set the event loop for the current context (python thread) to loop.            This is only permitted if the thread has no thread default main context        with the main thread using the default main context.        """        # Only accept glib event loops, otherwise things will just mess up        assert loop is None or isinstance(loop, GLibEventLoop)            ctx = ctx_td = GLib.MainContext.get_thread_default()        if ctx is None and threading.current_thread() is threading.main_thread():            ctx = GLib.MainContext.default()            if loop is None:            # We do permit unsetting the current loop/context            old = self._loops.pop(hash(ctx), None)            if old:                if hash(old._context) != hash(ctx):                    warnings.warn(                        "GMainContext was changed unknowingly by asyncio integration!",                        RuntimeWarning,                    )                if ctx_td:                    GLib.MainContext.pop_thread_default(ctx_td)        else:            # Only allow attaching if the thread has no main context yet            if ctx:>               raise RuntimeError(                    f"Thread {threading.current_thread().name!r} already has a main context, "                    "get_event_loop() will create a new loop if needed"                )E               RuntimeError: Thread 'MainThread' already has a main context, get_event_loop() will create a new loop if neededusr/lib64/python3.14/site-packages/gi/events.py:813: RuntimeErrorDuring handling of the above exception, another exception occurred:fixturedef = <FixtureDef argname='_function_scoped_runner' scope='function' baseid=''>request = <SubRequest '_function_scoped_runner' for <Coroutine test_foo>>    @pytest.hookimpl(wrapper=True)    def pytest_fixture_setup(fixturedef: FixtureDef, request) -> object | None:        asyncio_mode = _get_asyncio_mode(request.config)        if not _is_asyncio_fixture_function(fixturedef.func):            if asyncio_mode == Mode.STRICT:                # Ignore async fixtures without explicit asyncio mark in strict mode                # This applies to pytest_trio fixtures, for example>               return (yield)usr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:681: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ usr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:756: in _scoped_runner    with _temporary_event_loop_policy(new_loop_policy):usr/lib64/python3.14/contextlib.py:162: in __exit__    self.gen.throw(value)usr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:546: in _temporary_event_loop_policy    _set_event_loop(old_loop)usr/lib/python3.14/site-packages/pytest_asyncio/plugin.py:575: in _set_event_loop    asyncio.set_event_loop(loop)usr/lib64/python3.14/asyncio/events.py:839: in set_event_loop    _get_event_loop_policy().set_event_loop(loop)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <gi.events.GLibEventLoopPolicy object at 0x7f81069ecc20>loop = <GLibEventLoop running=False closed=False debug=False ctx=0x5FB5B1762B90 loop=0x5FB5B19B7110>    def set_event_loop(self, loop):        """Set the event loop for the current context (python thread) to loop.            This is only permitted if the thread has no thread default main context        with the main thread using the default main context.        """        # Only accept glib event loops, otherwise things will just mess up        assert loop is None or isinstance(loop, GLibEventLoop)            ctx = ctx_td = GLib.MainContext.get_thread_default()        if ctx is None and threading.current_thread() is threading.main_thread():            ctx = GLib.MainContext.default()            if loop is None:            # We do permit unsetting the current loop/context            old = self._loops.pop(hash(ctx), None)            if old:                if hash(old._context) != hash(ctx):                    warnings.warn(                        "GMainContext was changed unknowingly by asyncio integration!",                        RuntimeWarning,                    )                if ctx_td:                    GLib.MainContext.pop_thread_default(ctx_td)        else:            # Only allow attaching if the thread has no main context yet            if ctx:>               raise RuntimeError(                    f"Thread {threading.current_thread().name!r} already has a main context, "                    "get_event_loop() will create a new loop if needed"                )E               RuntimeError: Thread 'MainThread' already has a main context, get_event_loop() will create a new loop if neededusr/lib64/python3.14/site-packages/gi/events.py:813: RuntimeError================================== warnings summary ==================================usr/lib64/python3.14/site-packages/gi/events.py:718  /usr/lib64/python3.14/site-packages/gi/events.py:718: DeprecationWarning: 'asyncio.AbstractEventLoopPolicy' is deprecated and slated for removal in Python 3.16    class GLibEventLoopPolicy(asyncio.AbstractEventLoopPolicy):testcase.py:5  /testcase.py:5: DeprecationWarning: 'asyncio.set_event_loop_policy' is deprecated and slated for removal in Python 3.16    asyncio.set_event_loop_policy(GLibEventLoopPolicy())-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html============================== short test summary info ===============================ERROR testcase.py::test_foo - RuntimeError: Thread 'MainThread' already has a main context, get_event_loop() wi...

Non-minimal failure:https://gitlab.com/QubesOS/qubes-desktop-linux-menu/-/jobs/11350892441

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp