You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
using asyncio.iscoroutinefunction() on a functools.partial object #67707
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2015-02-26.17:52:33.200>created_at=<Date2015-02-25.11:00:39.941>labels= ['type-feature', 'invalid', 'expert-asyncio']
title='using asyncio.iscoroutinefunction() on a functools.partial object'updated_at=<Date2017-06-09.02:28:01.054>user='https://github.com/mathieui'
I recall discussing this before (maybe on the tulip list). I am firmly against. It is a slippery slope -- why inspect a partial but not a lambda? Plus there is no use case.
Mathieu: can you maybe give some examples? How are you using functools.partial with coroutines?
mathieui commented on Feb 26, 2015
mathieuimannequin
MannequinAuthor
More actions
Using functools.partial with coroutines would be mostly out of convenience, in order to avoid having factories in that return parametrized coroutine functions. I guess in such cases it might be better to create a two-lines wrapper around partial() to make it return a coroutine rather than change the stdlib for that.
In the attached file is an example of such use, where EventNotifier is a Protocol which receives external events and triggers event handlers based on that, and where the add_event_handler function checks if the handler is a coroutine function. In which case it uses asyncio.async to schedule the handler call; otherwise it uses loop.call_soon.
Yeah, your "add event handler" routine shouldn't be so picky to insist that iscoroutinefunction() returns True. It should just call the thing and verify that it has returned a coroutine object (asyncio.iscoroutine()).
I want to register many callbacks, but use only one handler and an argument to differentiate it. I realize our callback systems should provide for a cookie, but it doesn't.
The callback registry makes sure iscoroutinefunction(handler) because we don't want to defer error checking to the distant future. But iscoroutinefunction() returns False for the partial function. I was hopeful that this might work, but alas, no:
So can I close this? (I'm not sure what happened here exactly, I don't recall reopening, maybe GitHub did something funky?)
ah I thought you were cryptically telling me the issue was still valid when you re-opened this - it caused me to re-read the issue and find that it is actually still a bug - although now only relevant on python 3.10 and maybe on 3.11
I have a PR to fix it here #94907 but I think it would be better to drop asyncio.iscoroutinefunction, asyncio.coroutines._is_coroutine and all their usages.
This would require making _wrap_awaitable a real async fn - or a @types.coroutine function
Honestly if this is fixed in 3.11 by deleting asyncio.coroutine I would leave 3.10 alone.
Deleting asyncio.iscoroutinefunction would be problematic since it is ostensibly public so would have to be deprecated. But it sounds like you believe it could just become an alias for inspect.iscoroutinefunction if we change _wrap_awaitable? That sounds like we could do (though it's a bit late for 3.11 -- in main a.k.a. 3.12 I'd be okay with this though).
Activity
mathieui commentedon Feb 25, 2015
Using iscoroutinefunction() on an object returned by functools.partial() should return True if the function wrapped was a coroutine function.
(a recursive loop like the one in asyncio/events.py get_function_source() may be what needs to be done)
vstinner commentedon Feb 25, 2015
Take a look at asyncio.events._get_function_source() which supports wrapped functions and functools.partial.
Can you propose a patch?
If iscoroutinefunction() becomes "expensive", we might make checks optional, only run them in debug mode.
gvanrossum commentedon Feb 25, 2015
I recall discussing this before (maybe on the tulip list). I am firmly against. It is a slippery slope -- why inspect a partial but not a lambda? Plus there is no use case.
vstinner commentedon Feb 26, 2015
Mathieu: can you maybe give some examples? How are you using functools.partial with coroutines?
mathieui commentedon Feb 26, 2015
Using functools.partial with coroutines would be mostly out of convenience, in order to avoid having factories in that return parametrized coroutine functions. I guess in such cases it might be better to create a two-lines wrapper around partial() to make it return a coroutine rather than change the stdlib for that.
In the attached file is an example of such use, where EventNotifier is a Protocol which receives external events and triggers event handlers based on that, and where the add_event_handler function checks if the handler is a coroutine function. In which case it uses asyncio.async to schedule the handler call; otherwise it uses loop.call_soon.
You can close this, I guess.
gvanrossum commentedon Feb 26, 2015
Yeah, your "add event handler" routine shouldn't be so picky to insist that iscoroutinefunction() returns True. It should just call the thing and verify that it has returned a coroutine object (asyncio.iscoroutine()).
curtmcd commentedon Jun 9, 2017
There are use cases for this. I hit the problem and eventually wound up here, so I'd like to make a case to re-open.
My project has a callback registry of asyncio handler routines.
I want to register many callbacks, but use only one handler and an argument to differentiate it. I realize our callback systems should provide for a cookie, but it doesn't.
The callback registry makes sure iscoroutinefunction(handler) because we don't want to defer error checking to the distant future. But iscoroutinefunction() returns False for the partial function. I was hopeful that this might work, but alas, no:
gvanrossum commentedon Jun 9, 2017
Use a lambda instead of partial. It's more pythonic.
graingert commentedon Jul 16, 2022
this is fixed in #79071
graingert commentedon Jul 16, 2022
looking at this more closely - this is a bug in
asyncio.iscoroutinefunctionthat was fixed forinspect.iscoroutinefunctionthis code will now work - if you use
async def handler(detail):here's a demo:
gvanrossum commentedon Jul 16, 2022
So can I close this? (I'm not sure what happened here exactly, I don't recall reopening, maybe GitHub did something funky?)
graingert commentedon Jul 16, 2022
ah I thought you were cryptically telling me the issue was still valid when you re-opened this - it caused me to re-read the issue and find that it is actually still a bug - although now only relevant on python 3.10 and maybe on 3.11
graingert commentedon Jul 16, 2022
I have a PR to fix it here #94907 but I think it would be better to drop
asyncio.iscoroutinefunction,asyncio.coroutines._is_coroutineand all their usages.This would require making
_wrap_awaitablea real async fn - or a@types.coroutinefunctiongvanrossum commentedon Jul 17, 2022
Honestly if this is fixed in 3.11 by deleting
asyncio.coroutineI would leave 3.10 alone.Deleting
asyncio.iscoroutinefunctionwould be problematic since it is ostensibly public so would have to be deprecated. But it sounds like you believe it could just become an alias forinspect.iscoroutinefunctionif we change_wrap_awaitable? That sounds like we could do (though it's a bit late for 3.11 -- in main a.k.a. 3.12 I'd be okay with this though).graingert commentedon Jul 17, 2022
I opened an issue for that removal #94912
gvanrossum commentedon Jul 17, 2022
Okay, closing this issue as fixed.