[Python-ideas] PEP 550 v2
Yury Selivanov
yselivanov.ml at gmail.com
Wed Aug 16 12:55:55 EDT 2017
On Wed, Aug 16, 2017 at 12:51 PM, Yury Selivanov
<yselivanov.ml at gmail.com> wrote:
> On Wed, Aug 16, 2017 at 5:36 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> On 16 August 2017 at 17:18, Nathaniel Smith <njs at pobox.com> wrote:
>> [Yury wrote]
> [..]
>>>> * If ``coro.cr_local_context`` is an empty ``LocalContext`` object
>>>> that ``coro`` was created with, the interpreter will set
>>>> ``coro.cr_local_context`` to ``None``.
>>>
>>> I like all the ideas in this section, but this specific point feels a
>>> bit weird. Coroutine objects need a second hidden field somewhere to
>>> keep track of whether the object they end up with is the same one they
>>> were created with?
>>
>> It feels odd to me as well, and I'm wondering if we can actually
>> simplify this by saying:
>>
>> 1. Generator contexts (both sync and async) are isolated by default
>> (__local_context__ = LocalContext())
>> 2. Coroutine contexts are *not* isolated by default (__local_context__ = None)
>>
>> Running top level task coroutines in separate execution contexts then
>> becomes the responsibility of the event loop, which the PEP already
>> lists as a required change in 3rd party libraries to get this all to
>> work properly.
>
> This is an interesting twist, and I like it.
>
> This will change asyncio.Task from:
>
> class Task:
>
> def __init__(self, coro):
> ...
> self.exec_context = sys.get_execution_context()
>
> def step():
>
> sys.run_with_execution_context(self.coro.send)
>
>
> to:
>
> class Task:
>
> def __init__(self, coro):
> ...
> self.local_context = sys.new_local_context()
>
> def step():
>
> sys.run_with_local_context(self.local_context, self.coro.send)
>
> And we don't need ceval to do anything for "await", which means that
> with this approach we won't touch ceval.c at all.
And immediately after I hit "send" I realized that this is a bit more
complicated.
In order for Tasks to remember the full execution context of where
they were created, we need a new method that would allow to run with
*both* exec and local contexts:
class Task:
def __init__(self, coro):
...
self.local_context = sys.new_local_context()
self.exec_context = sys.get_execution_context()
def step():
sys.run_with_contexts(self.exec_context, self.local_context,
self.coro.send)
This is needed for the following PEP example to work properly:
current_request = sys.new_context_item(description='request')
async def child():
print('current request:', repr(current_request.get()))
async def handle_request(request):
current_request.set(request)
event_loop.create_task(child)
run(top_coro())
See https://www.python.org/dev/peps/pep-0550/#tasks
Yury
More information about the Python-ideas
mailing list