Skip to content

Usecase for nested run (and blocking outside runer) #608

@Carreau

Description

@Carreau

Hi There,

I'm working on adding some Async support to IPython, which basically convert the core to most of it being coroutine. I'm ending up with a use case where I'd actually like to call trio.run() from within trio.run() which you can't because of :

if hasattr(GLOBAL_RUN_CONTEXT, "runner"):
        raise RuntimeError("Attempted to call run() from inside a run()")

Yes, I know, run inside run is a footgun, but in my case it's to call nested IPython.embed(), so you literally want to halt the outer embed, and start a new loop;
I'm using the following that seem to work:

from contextlib import contextmanager
 _sentinel = object()
@contextmanager
def new_context():
    import trio._core._run as tcr
    old_runner = getattr(tcr.GLOBAL_RUN_CONTEXT, 'runner', _sentinel)
    old_task = getattr(tcr.GLOBAL_RUN_CONTEXT, 'task', None)
    if old_runner is not _sentinel:
        del tcr.GLOBAL_RUN_CONTEXT.runner
    tcr.GLOBAL_RUN_CONTEXT.task = None
    yield
    if old_runner is not _sentinel:
        tcr.GLOBAL_RUN_CONTEXT.runner = old_runner
    tcr.GLOBAL_RUN_CONTEXT.task = old_task

Is there a better way ?
If not, does that seem "Ok-ish", or do you see any other things I need to watch out for ?

I know this is internals API, and I'm not requesting it to be stable, if they change, well so be it, and I'll mark the nested-embed in IPython as "Brittle and depends on some non-vetted code", but still really like to keep the functionality for some users.

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions