Movatterモバイル変換
[0]ホーム
[Python-Dev] Using async/await in place of yield expression
Nathaniel Smithnjs at pobox.com
Mon Nov 27 03:41:55 EST 2017
On Sun, Nov 26, 2017 at 9:33 PM, Caleb Hattingh<caleb.hattingh at gmail.com> wrote:> The PEP only says that __await__ must return an iterator, but it turns out> that it's also required that that iterator> should not return any intermediate values.I think you're confused :-). When the iterator yields an intermediatevalue, it does two things:(1) it suspends the current call stack and returns control to thecoroutine runner (i.e. the event loop)(2) it sends some arbitrary value back to the coroutine runnerThe whole point of `await` is that it can do (1) -- this is what letsyou switch between executing different tasks, so they can pretend toexecute in parallel. However, you do need to make sure that your__await__ and your coroutine runner are on the same page with respectto (2) -- if you send a value that the coroutine runner isn'texpecting, it'll get confused. Generally async libraries control boththe coroutine runner and the __await__ method, so they get to inventwhatever arbitrary convention they want.In asyncio, the convention is that the values you send back must beFuture objects, and the coroutine runner interprets this as a requestto wait for the Future to be resolved, and then resume the currentcall stack. In curio, the convention is that you send back a specialtuple describing some operation you want the event loop to perform[1], and then it resumes your call stack once that operation hasfinished. And Trio barely uses this channel at all. (It does transfera bit of information that way for convenience/speed, but the main workof setting up the task to be resumed at the appropriate time happensthrough other mechanisms.)What you observed is that the asyncio coroutine runner gets cranky ifyou send it an integer when it was expecting a Future.Since most libraries assume that they control both __await__ and thecoroutine runner, they don't tend to give great error messages here(though trio does [2] ;-)). I think this is also why the asyncio docsdon't talk about this. I guess in asyncio's case it is technically asemi-public API because you need to know how it works if you're theauthor of a library like tornado or twisted that wants to integratewith asyncio. But most people aren't the authors of tornado ortwisted, and the ones who are already know how this works, so the lackof docs isn't a huge deal in practice...-n[1]https://github.com/dabeaz/curio/blob/bd0e2cb7741278d1d9288780127dc0807b1aa5b1/curio/traps.py#L48-L156[2]https://github.com/python-trio/trio/blob/2b8e297e544088b98ff758d37c7ad84f74c3f2f5/trio/_core/_run.py#L1521-L1530-- Nathaniel J. Smith --https://vorpus.org
More information about the Python-Devmailing list
[8]ページ先頭