Pythonバイトコードを簡単に見てみる。

# 1. Pythonのバイトコード
## 1.1. バイトコードコンパイル
`py`から`pyc`を出力する。

```bash
python3 -m compileall s1.py
```
- [compileall — Byte-compile Python libraries](https://docs.python.org/3/library/compileall.html)

## 1.2. バイトコードディスアセンブル
Python3の場合、以下のコマンドを入れて、ディスアセンブルを行う。

```bash
sudo apt install uncompyle6
```
以下で、ディスアセンブルできる。`-t`,`-a`,`-g`,`-verify`,`-verify-run`等が役に立つ。

```bash
uncompyle6 __pycache__/s1.cpython-38.pyc
```

例えば、`-t`でコンパイルした場合、以下のデータが出力される。ここで、`LOAD_GLOBAL`等が、Pythonインタープリターの命令である。このため、大まかな処理がどうなっているか見ることができる。

```bash
# uncompyle6 version 3.7.1
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.2 (default, Apr 27 2020, 15:53:34)
# [GCC 9.3.0]
# Embedded file name: s1.py
# Compiled at: 2020-06-23 10:28:06
# Size of source mod 2**32: 172 bytes
stmts (2)
     0. sstmt
        function_def (2)
             0. mkfunc (3)
                 0.  L.   1         0  LOAD_CODE                <code_object main>
                 1.                 2  LOAD_STR                 'main'
                 2.                 4  MAKE_FUNCTION_0          'Neither defaults, keyword-only args, annotations, nor closures'
             1. store
                                6  STORE_NAME               main
     1. sstmt
        call_stmt (2)
             0. expr
                call (2)
                     0. expr
                         L.   8         8  LOAD_NAME                main
                     1.                10  CALL_FUNCTION_0       0  ''
             1.                12  POP_TOP

---- end before transform
---- begin after transform
    stmts (2)
     0. function_def (2)
         0. mkfunc (3)
             0.  L.   1         0  LOAD_CODE                <code_object main>
             1.                 2  LOAD_STR                 'main'
             2.                 4  MAKE_FUNCTION_0          'Neither defaults, keyword-only args, annotations, nor closures'
         1. store
                            6  STORE_NAME               main
     1. call_stmt (2)
         0. expr
            call (2)
                 0. expr
                     L.   8         8  LOAD_NAME                main
                 1.                10  CALL_FUNCTION_0       0  ''
         1.                12  POP_TOP
stmts (2)
     0. sstmt
        assign (2)
             0. expr
                 L.   2         0  LOAD_CONST               0.0
             1. store
                                2  STORE_FAST               'total'
     1. sstmt
        for38 (4)
             0. expr
                call (3)
                     0. expr
                         L.   3         4  LOAD_GLOBAL              enumerate
                     1. pos_arg
                        expr
                            call (3)
                                 0. expr
                                                    6  LOAD_GLOBAL              range
                                 1. pos_arg
                                    expr
                                                        8  LOAD_CONST               10000
                                 2.                10  CALL_FUNCTION_1       1  ''
                     2.                12  CALL_FUNCTION_1       1  ''
             1. get_for_iter (3)
                 0.                14  GET_ITER
                 1. _come_froms
                 2.                16  FOR_ITER             62  'to 62'
             2. store
                unpack (3)
                     0.                18  UNPACK_SEQUENCE_2     2
                     1. store
                                       20  STORE_FAST               'i'
                     2. store
                                       22  STORE_FAST               '_'
             3. for_block
                l_stmts (2)
                     0. for38 (5)
                         0. expr
                            call (3)
                                 0. expr
                                     L.   4        24  LOAD_GLOBAL              enumerate
                                 1. pos_arg
                                    expr
                                        call (4)
                                             0. expr
                                                               26  LOAD_GLOBAL              range
                                             1. pos_arg
                                                expr
                                                                   28  LOAD_CONST               1
                                             2. pos_arg
                                                expr
                                                                   30  LOAD_CONST               10000
                                             3.                32  CALL_FUNCTION_2       2  ''
                                 2.                34  CALL_FUNCTION_1       1  ''
                         1. get_for_iter (3)
                             0.                36  GET_ITER
                             1. _come_froms
                             2.                38  FOR_ITER             60  'to 60'
                         2. store
                            unpack (3)
                                 0.                40  UNPACK_SEQUENCE_2     2
                                 1. store
                                                   42  STORE_FAST               'j'
                                 2. store
                                                   44  STORE_FAST               '_'
                         3. for_block (2)
                             0. l_stmts
                                aug_assign1 (4)
                                     0. expr
                                         L.   5        46  LOAD_FAST                'total'
                                     1. expr
                                        bin_op (3)
                                             0. expr
                                                               48  LOAD_FAST                'i'
                                             1. expr
                                                               50  LOAD_FAST                'j'
                                             2. binary_operator
                                                               52  BINARY_MULTIPLY
                                     2. inplace_op
                                                       54  INPLACE_ADD
                                     3. store
                                                       56  STORE_FAST               'total'
                             1.                58  JUMP_BACK            38  'to 38'
                         4.                60  JUMP_BACK            16  'to 16'
                     1. lstmt
                        call_stmt (2)
                             0. expr
                                call (4)
                                     0. expr
                                         L.   6        62  LOAD_GLOBAL              print
                                     1. pos_arg
                                        expr
                                                           64  LOAD_STR                 'total='
                                     2. pos_arg
                                        expr
                                                           66  LOAD_FAST                'total'
                                     3.                68  CALL_FUNCTION_2       2  ''
                             1.                70  POP_TOP
stmts (2)
     0. assign (2)
         0. expr
             L.   2         0  LOAD_CONST               0.0
         1. store
                            2  STORE_FAST               'total'
     1. for38 (4)
         0. expr
            call (3)
                 0. expr
                     L.   3         4  LOAD_GLOBAL              enumerate
                 1. pos_arg
                    expr
                        call (3)
                             0. expr
                                                6  LOAD_GLOBAL              range
                             1. pos_arg
                                expr
                                                    8  LOAD_CONST               10000
                             2.                10  CALL_FUNCTION_1       1  ''
                 2.                12  CALL_FUNCTION_1       1  ''
         1. get_for_iter (3)
             0.                14  GET_ITER
             1. _come_froms
             2.                16  FOR_ITER             62  'to 62'
         2. store
            unpack (3)
                 0.                18  UNPACK_SEQUENCE_2     2
                 1. store
                                   20  STORE_FAST               'i'
                 2. store
                                   22  STORE_FAST               '_'
         3. for_block
            l_stmts (2)
                 0. for38 (5)
                     0. expr
                        call (3)
                             0. expr
                                 L.   4        24  LOAD_GLOBAL              enumerate
                             1. pos_arg
                                expr
                                    call (4)
                                         0. expr
                                                           26  LOAD_GLOBAL              range
                                         1. pos_arg
                                            expr
                                                               28  LOAD_CONST               1
                                         2. pos_arg
                                            expr
                                                               30  LOAD_CONST               10000
                                         3.                32  CALL_FUNCTION_2       2  ''
                             2.                34  CALL_FUNCTION_1       1  ''
                     1. get_for_iter (3)
                         0.                36  GET_ITER
                         1. _come_froms
                         2.                38  FOR_ITER             60  'to 60'
                     2. store
                        unpack (3)
                             0.                40  UNPACK_SEQUENCE_2     2
                             1. store
                                               42  STORE_FAST               'j'
                             2. store
                                               44  STORE_FAST               '_'
                     3. for_block (2)
                         0. l_stmts
                            aug_assign1 (4)
                                 0. expr
                                     L.   5        46  LOAD_FAST                'total'
                                 1. expr
                                    bin_op (3)
                                         0. expr
                                                           48  LOAD_FAST                'i'
                                         1. expr
                                                           50  LOAD_FAST                'j'
                                         2. binary_operator
                                                           52  BINARY_MULTIPLY
                                 2. inplace_op
                                                   54  INPLACE_ADD
                                 3. store
                                                   56  STORE_FAST               'total'
                         1.                58  JUMP_BACK            38  'to 38'
                     4.                60  JUMP_BACK            16  'to 16'
                 1. lstmt
                    call_stmt (2)
                         0. expr
                            call (4)
                                 0. expr
                                     L.   6        62  LOAD_GLOBAL              print
                                 1. pos_arg
                                    expr
                                                       64  LOAD_STR                 'total='
                                 2. pos_arg
                                    expr
                                                       66  LOAD_FAST                'total'
                                 3.                68  CALL_FUNCTION_2       2  ''
                         1.                70  POP_TOP


def main
---- end before transform
---- begin after transform

():
    total = 0.0
    for i, _ in enumerate(range(10000)):
        for j, _ in enumerate(range(1, 10000)):
            total += i * j

        print('total=', total)


main()
# okay decompiling __pycache__/s1.cpython-38.pyc
```
## 1.3. バイトコード命令
`LOAD_GLOBAL`等のPythonインタープリターの命令が、121程度`opcode.h`で定義されている。そして、その命令を`ceval.c`で処理する。

- [dis --- Python バイトコードの逆アセンブラ](https://docs.python.org/ja/3/library/dis.html#python-bytecode-instructions)
- [Include/opcode.h](https://github.com/python/cpython/blob/3.8/Include/opcode.h)
- [Python/ceval.c](https://github.com/python/cpython/blob/3.8/Python/ceval.c)
   - `LOAD_GLOBAL`等のPythonインタープリターの命令の処理がここで実装されている。
   - また、コンパイル時に`OPCACHE_STATS`を設定すると`LOAD_GLOBAL`のキャッシュヒット率等を見ることができる。

## 1.4. 参考資料
- [Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜](https://www.slideshare.net/pfi/python-61443627)
- [Pythonが動く仕組み(の概要)](https://www.slideshare.net/yotchang4s/howpythonworkspyconjp2017lt-79553671?next_slideshow=1)