So kompilieren Sie Python

Hallo Habr!





Ich möchte Ihnen von einem erstaunlichen Ereignis erzĂ€hlen, von dem ich vor ein paar Monaten erfahren habe. Es stellt sich heraus, dass ein beliebtes Python-Dienstprogramm seit ĂŒber einem Jahr als BinĂ€rdateien verteilt wird, die direkt aus Python kompiliert werden. Und es geht nicht um banale Verpackung von einigen PyInstaller , sondern um ehrlich Ahead-of-time Kompilierung des gesamten Python - Pakets. Wenn Sie so ĂŒberrascht sind wie ich, willkommen bei cat.





Lassen Sie mich erklĂ€ren, warum ich dieses Ereignis wirklich erstaunlich finde. Es gibt zwei Arten der Kompilierung:  AOT (Ahead-of-Time) , wenn der gesamte Code vor dem Starten des Programms kompiliert wird, und Just-in-Time-Compiler (JIT) , wenn das Programm wĂ€hrend seiner AusfĂŒhrung direkt fĂŒr die erforderliche Prozessorarchitektur kompiliert wird . Im zweiten Fall wird der erste Start des Programms von einer virtuellen Maschine oder einem Interpreter ausgefĂŒhrt.





Wenn wir beliebte Programmiersprachen nach Kompilierungstyp gruppieren, erhalten wir die folgende Liste:





  • Ahead-of-Time-Compiler: C, C ++, Rust, Kotlin, Nim, D, Go, Dart;





  • Just-in-Time-Compiler: Lua, C #, Groovy, Dart.





In Python gibt es keinen sofort einsatzbereiten JIT-Compiler, aber separate Bibliotheken, die eine solche Möglichkeit bieten, gibt es schon seit langer Zeit





, : . : 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 Extension — CPython , /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_Add — Python, , 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