Como compilar Python

Olá, Habr!





Quero contar a vocês sobre um evento incrível que aprendi alguns meses atrás. Acontece que um utilitário python popular foi distribuído por mais de um ano como binários que são compilados diretamente do python. E não se trata de empacotamento banal por algum PyInstaller , mas de compilação honesta e antecipada de todo o pacote python. Se você está tão surpreso quanto eu, seja bem-vindo ao gato.





Deixe-me explicar por que acho esse evento realmente incrível. Existem dois tipos de compilação:  Ahead-of-time (AOT) , quando todo o código é compilado antes de iniciar o programa, e Just in time compiler (JIT) , quando o programa é compilado diretamente para a arquitetura de processador necessária durante sua execução . No segundo caso, o lançamento inicial do programa é feito por uma máquina virtual ou intérprete.





Se agruparmos as linguagens de programação populares por tipo de compilação, obteremos a seguinte lista:





  • Compilador antecipado: C, C ++, Rust, Kotlin, Nim, D, Go, Dart;





  • Compilador just in time: Lua, C #, Groovy, Dart.





Não existe um compilador JIT pronto para uso em Python, mas bibliotecas separadas que oferecem essa oportunidade já existem há muito tempo





, : . : Kotlin JIT JavaVM, AOT Kotlin/Native. Dart ( 2). A JIT-, . 





, , . .





JIT , . JIT . AOT , ? , .





, , . mypy - python-.





2019 , . — mypyc. , “ 4 Python-” mypy ( : 1, 2, 3). mypyc: mypy python- Dropbox, , . , : go cython. — AOT python-.





, mypy , . mypy “” python, , mypyc .





, , python-. Python c 3.4 , mypy . , python , AOT . , mypyc !





bubble_sort

“”.  lib.py:





def bubble_sort(data):
   n = len(data)
   for i in range(n - 1):
       for j in range(n - i - 1):
           if data[j] > data[j + 1]:
               buff = data[j]
               data[j] = data[j + 1]
               data[j + 1] = buff
   return data
      
      



, mypyc . , mypyc. , mypy, mypyc ! mypyc, :





> mypyc lib.py
      
      



:





  • .mypy_cache



      — mypy , mypyc mypy AST;





  • build



    — ;





  • lib.cpython-38-x86_64-linux-gnu.so



    — . CPython Extension.





CPython ExtensionCPython , /C++. , CPython lib. , python.





:





  1. python ;





  2. .so , mypyc gcc (gcc python-dev ).





lib.cpython-38-x86_64-linux-gnu.so



lib.py , .





. main.py :





import lib


data = lib.bubble_sort(list(range(5000, 0, -1)))

assert data == list(range(1, 5001))
      
      



:













real 5.68





user 5.60





sys 0.01





real 2.78





user 2.73





sys 0.01





(~ 2 ), , . .





“ ”, . , .  





sum(a, b)

:





def sum(a, b):
  return a + b
      
      



:





int sum(int a, int b) {
   return a + b;
}
      
      



c ( ):





PyObject *CPyDef_sum(PyObject *cpy_r_a, PyObject *cpy_r_b){
    return PyNumber_Add(cpy_r_a, cpy_r_b);
}
      
      



, . -, , PyObject, CPython . , , : , , , , . mypyc? 





, : CPython . PyNumber_AddPython, , Python .





CPython c Extension :





 — - sum A, B;





 — , , A + B;





 — ;





 — , - .





: , ,





, , , mypyc , .





sum(a: int, b: int)

, python, , , . , . , CPython - Extension. ? 





, , , , CPython. mypyc , . mypyc , , sum. , , . , -, :





def sum(a: int, b: int):
  return a + b
      
      



C ( ):





PyObject *CPyDef_sum(CPyTagged cpy_r_a, CPyTagged cpy_r_b) {
   CPyTagged cpy_r_r0;
   PyObject *cpy_r_r1;
   cpy_r_r0 = CPyTagged_Add(cpy_r_a, cpy_r_b);
   cpy_r_r1 = CPyTagged_StealAsObject(cpy_r_r0);

   return cpy_r_r1;
}
      
      



, : , , . , . 





CPyDef_sum PyObject, CPyTagged. int, CPython, mypyc, . , sum int .





CPyTaggetAdd PyNumber_Add. mypyc. CPyTaggetAdd, , a b, int, , :





if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
    CPyTagged sum = left + right;

    if (likely(!CPyTagged_IsAddOverflow(sum, left, right))) {
        return sum;
    }
}
      
      



, CPython - Extension :





 — - sum A, B;





 — , .





bubble_sort(data: List[int])

, . , data:





def bubble_sort(data: List[int]):
    …
      
      



:









,









real 5.68





user 5.60





sys 0.01





real 2.78





user 2.73





sys 0.01





real 1.32





user 1.30





sys 0.01





, , , !





mypyc

, , . mypyc : , , , mypy. mypy . python-, , .





, , :





  • ;





  • monkey patching;





  • Mypy , .





. , , abc. , . , gcc , , , . , , 20 % , .





, Roadmap , .





Nuitka

, . Nuitka . , Nuitka Python ++ , Python Extension. , CPython libpython.





Nuitka , . mypy .





, mypy : , “ ”, PyCharm . , mypy. , . , python. mypy — , . , CPython , , . (, mypyc ). , mypyc , , , - , mypyc, , , mypy.





P.S.

, python, . , mypyc, , , .





UPD

, python - Cython, python ( cython-). cython , (real 1.82) mypyc . .








All Articles