5

As stated in this question, we can turn a function into a coroutine using the asyncio.coroutine decorator to turn a function into a coroutine like so:

def hello():
    print('Hello World!')

async_hello = asyncio.coroutine(hello)

However this function is deprecated as of python 3.8 (replaced by async def ...). So how can we do this in 3.8+ without async def ...?

5
  • 1
    Can you please add more information about what you are actually trying to achieve - why are you trying to turn the function into a coroutine in the first place? If the function is sync, you can always just call it from async code. You gain nothing by changing it into a coroutine because it doesn't await anything, so it never suspends. Commented Mar 5, 2021 at 10:47
  • 1
    @user4815162342 Converting a sync function to async is useful to feed it to other code that expects a coroutine. Whether a function is called or called+await'ed is not always controllable from the outside. Commented Mar 5, 2021 at 10:59
  • 1
    @user4815162342 exactly what @MisterMiyagi said :P. I have a function which grabs and calls a function from a dictionary, expecting it to be a coroutine. I want to be able to convert one of these functions - func - from a syncronous function into a coroutine - func needs to be called from syncronous code as well, so I can't make it async. Commented Mar 5, 2021 at 11:14
  • 1
    @MisterMiyagi But it should be trivial to create an async wrapper that just invokes the function, such a thing doesn't even a generic solution. The coroutine decorator was never meant for that usage, it was meant specifically to convert a generator into an asyncio-compatible coroutine. (I'm kind of surprised that it even works on non-generators...) Commented Mar 5, 2021 at 11:15
  • @user4815162342 Yes, I'm also surprised that asyncio.coroutine worked in the first place. But seeing how it does and is suggested on SO, I do not find its usage here particularly surprising (not that I would recommend it...). Commented Mar 5, 2021 at 11:19

1 Answer 1

9

Define a custom coroutine wrapper that merely calls the function:

from functools import wraps

def awaitify(sync_func):
    """Wrap a synchronous callable to allow ``await``'ing it"""
    @wraps(sync_func)
    async def async_func(*args, **kwargs):
        return sync_func(*args, **kwargs)
    return async_func

This can be used to make an arbitrary synchronous function compatible wherever a coroutine is expected.

def hello():
    print('Hello World!')

async_hello = awaitify(hello)
asyncio.run(async_hello())  # Hello World!
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.