[Python-Dev] PEP 492: What is the real goal?

Yury Selivanov yselivanov.ml at gmail.com
Fri May 1 23:58:26 CEST 2015

On 2015-05-01 5:37 PM, Jim J. Jewett wrote:
> On Thu Apr 30 21:27:09 CEST 2015, Yury Selivanov replied:
> On 2015-04-30 2:41 PM, Jim J. Jewett wrote:
>>> Bad phrasing on my part.  Is there anything that prevents an
>>> asynchronous call (or waiting for one) without the "async with"?
>>> If so, I'm missing something important.  Either way, I would
>>> prefer different wording in the PEP.
>> Yes, you can't use 'yield from' in __exit__/__enter__
>> in current Python.
> I tried it in 3.4, and it worked.
> I'm not sure it would ever be sensible, but it didn't raise any
> errors, and it did run.
> What do you mean by "can't use"?

It probably executed without errors, but it didn't run the

class Foo:
    def __enter__(self):
        yield from asyncio.sleep(0)

with Foo(): pass # <- 'spam' won't ever be printed.

>>>> For coroutines in PEP 492:
>>>> __await__ = __anext__ is the same as __call__ = __next__
>>>> __await__ = __aiter__ is the same as __call__ = __iter__
>>> That tells me that it will be OK sometimes, but will usually
>>> be either a mistake or an API problem -- and it explains why.
>>> Please put those 3 lines in the PEP.
>> There is a line like that:
>> https://www.python.org/dev/peps/pep-0492/#await-expression
>> Look for "Also, please note..." line.
> It was from reading the PEP that the question came up, and I
> just reread that section.
> Having those 3 explicit lines goes a long way towards explaining
> how an asychio coroutine differs from a regular callable, in a
> way that the existing PEP doesn't, at least for me.
>>>> This is OK. The point is that you can use 'await log' in
>>>> __aenter__.  If you don't need awaits in __aenter__ you can
>>>> use them in __aexit__. If you don't need them there too,
>>>> then just define a regular context manager.
>>> Is it an error to use "async with" on a regular context manager?
>>> If so, why?  If it is just that doing so could be misleading,
>>> then what about "async with mgr1, mgr2, mgr3" -- is it enough
>>> that one of the three might suspend itself?
>> 'with' requires an object with __enter__ and __exit__
>> 'async with' requires an object with __aenter__ and __aexit__
>> You can have an object that implements both interfaces.
> I'm not still not seeing why with (let alone await with) can't
> just run whichever one it finds.  "await with" won't actually let
> the BLOCK run until the future is resolved.  So if a context
> manager only supplies __enter__ instead of __aenter__, then at most
> you've lost a chance to switch tasks while waiting -- and that is no
> worse than if the context manager just happened to be really slow.

let's say you have a function:

def foo():
    with Ctx(): pass

if Ctx.__enter__ is a generator/coroutine, then
foo becomes a generator/coroutine (otherwise how
(and to what) would you yield from/await on __enter__?).
And then suddenly calling 'foo' doesn't do anything
(it will return you a generator/coroutine object).

This isn't transparent or even remotely

>>>>>> For debugging this kind of mistakes there is a special debug mode in
>>> Is the intent to do anything more than preface execution with:
>>> import asynchio.coroutines
>>> asynchio.coroutines._DEBUG = True
>> This won't work, unfortunately.  You need to set the
>> debug flag *before* you import asyncio package (otherwise
>> we would have an unavoidable performance cost for debug
>> features).  If you enable it after you import asyncio,
>> then asyncio itself won't be instrumented.  Please
>> see the implementation of asyncio.coroutine for details.
> Why does asynchio itself have to wrapped?  Is that really something
> normal developers need to debug, or is it only for developing the
> stdlib itself?  If it if only for developing the stdlib, than I
> would rather see workarounds like shoving _DEBUG into builtins
> when needed, as opposed to adding multiple attributes to sys.

Yes, normal developers need asyncio to be instrumented,
otherwise you won't know what you did wrong when you
called some asyncio code without 'await' for example.


More information about the Python-Dev mailing list