go-python / go-python/gpython

Getting started on asyncio

未关闭
#178 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Go
星标
1k
派生
105
PR 合并指标
30 天内没有已合并 PR

描述

I've been trying to understand how this project works, and also how we can support newer language versions. I've done some reading into how asyncio works, and I thought I would share that here. Sorry if this is not news to anybody, I'm not much of a python developer.

The co-routine introduced in python3.5 seem to be the biggest language feature we need to support to become current. The op codes can be found here: https://docs.python.org/3/library/dis.html#opcode-GET_AWAITABLE

A basic example program looks like:

```
import asyncio

async def foo():
return "test"

async def bar():
return await foo()

print(asyncio.run(bar()))
```

And produces the following bytecode:

```
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (asyncio)
6 STORE_NAME 0 (asyncio)

3 8 LOAD_CONST 2 ()
10 LOAD_CONST 3 ('foo')
12 MAKE_FUNCTION 0
14 STORE_NAME 1 (foo)

6 16 LOAD_CONST 4 ()
18 LOAD_CONST 5 ('bar')
20 MAKE_FUNCTION 0
22 STORE_NAME 2 (bar)

10 24 LOAD_NAME 3 (print)
26 LOAD_NAME 0 (asyncio)
28 LOAD_METHOD 4 (run)
30 LOAD_NAME 2 (bar)
32 CALL_FUNCTION 0
34 CALL_METHOD 1
36 CALL_FUNCTION 1
38 POP_TOP
40 LOAD_CONST 1 (None)
42 RETURN_VALUE

Disassembly of :
0 GEN_START 1

4 2 LOAD_CONST 1 ('test')
4 RETURN_VALUE

Disassembly of :
0 GEN_START 1

7 2 LOAD_GLOBAL 0 (foo)
4 CALL_FUNCTION 0
6 GET_AWAITABLE
8 LOAD_CONST 0 (None)
10 YIELD_FROM
12 RETURN_VALUE

```

The byte code of calling the functions is actually unchanged. The functions marked with `async` just have to return a co-routine object. The `GET_AWAITABLE` opcode seems to cast the other await-able types e.g. generators or classes that implement `self.__await__`.

We _might_ be able to implement this fairly easily by just wrapping the `Function` type in a `co-routine` type. To get any actual concurrency out of this implementation though, we need to implement the event loop API.

https://docs.python.org/3/library/asyncio-eventloop.html#:~:text=The%20event%20loop%20is%20the,asyncio%20functions%2C%20such%20as%20asyncio.

This is the hard part which actually allows creation of futures and tasks. I'm not sure if the `await for` byte code that was already implemented in 3.4 has all the features we need, but it looks like we can get pretty far with the byte code we have already.

The last piece of the puzzle is `select()` which allows us to wait on a socket while executing another co-routine.

There's a good write-up here:
https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。