Même moi, j'ai eu le même problème à comprendre en quoi CPython, JPython, IronPython, PyPy sont différents les uns des autres.
Donc, je suis prêt à effacer trois choses avant de commencer à expliquer:
- Python : C'est un langage, il indique / décrit uniquement comment vous transmettre / vous exprimer à l'interpréteur (le programme qui accepte votre code python).
- Mise en œuvre : tout dépend de la façon dont l'interprète a été écrit, en particulier dans quelle langue et ce qu'il finit par faire .
- Bytecode : C'est le code qui est traité par un programme, généralement appelé machine virtuelle, plutôt que par la "vraie" machine informatique, le processeur matériel.
CPython est l'implémentation, qui a été écrite en langage C. Il finit par produire du bytecode (jeu d'instructions basé sur la pile) qui est spécifique à Python, puis l'exécute. La raison pour convertir du code Python en un bytecode est parce qu'il est plus facile d'implémenter un interpréteur s'il ressemble à des instructions machine. Mais, il n'est pas nécessaire de produire du bytecode avant l'exécution du code Python (mais CPython le produit).
Si vous souhaitez consulter le bytecode de CPython, vous pouvez le faire. Voici comment vous pouvez:
>>> def f(x, y): # line 1
... print("Hello") # line 2
... if x: # line 3
... y += x # line 4
... print(x, y) # line 5
... return x+y # line 6
... # line 7
>>> import dis # line 8
>>> dis.dis(f) # line 9
2 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Hello')
4 CALL_FUNCTION 1
6 POP_TOP
3 8 LOAD_FAST 0 (x)
10 POP_JUMP_IF_FALSE 20
4 12 LOAD_FAST 1 (y)
14 LOAD_FAST 0 (x)
16 INPLACE_ADD
18 STORE_FAST 1 (y)
5 >> 20 LOAD_GLOBAL 0 (print)
22 LOAD_FAST 0 (x)
24 LOAD_FAST 1 (y)
26 CALL_FUNCTION 2
28 POP_TOP
6 30 LOAD_FAST 0 (x)
32 LOAD_FAST 1 (y)
34 BINARY_ADD
36 RETURN_VALUE
Voyons maintenant le code ci-dessus. Les lignes 1 à 6 sont une définition de fonction. À la ligne 8, nous importons le module 'dis' qui peut être utilisé pour afficher le bytecode Python intermédiaire (ou vous pouvez dire, le désassembleur pour le bytecode Python) généré par CPython (interprète).
REMARQUE : j'ai obtenu le lien vers ce code à partir du canal IRC #python: https://gist.github.com/nedbat/e89fa710db0edfb9057dc8d18d979f9c
Et puis, il y a Jython, qui est écrit en Java et finit par produire du code d'octet Java. Le code d'octet Java s'exécute sur Java Runtime Environment, qui est une implémentation de Java Virtual Machine (JVM). Si cela prête à confusion, je soupçonne que vous n'avez aucune idée du fonctionnement de Java. En termes simples, le code Java (le langage, pas le compilateur) est pris par le compilateur Java et génère un fichier (qui est du code d'octet Java) qui peut être exécuté uniquement à l'aide d'un JRE. Ceci est fait de sorte qu'une fois le code Java compilé, il puisse être porté sur d'autres machines au format de code octet Java, qui ne peut être exécuté que par JRE. Si cela prête toujours à confusion, vous voudrez peut-être consulter cette page Web .
Ici, vous pouvez demander si le bytecode de CPython est portable comme Jython, je ne le pense pas. Le bytecode produit dans l'implémentation de CPython était spécifique à cet interpréteur pour le rendre facile pour une exécution ultérieure du code (je soupçonne également que, une telle production de bytecode intermédiaire, juste pour la facilité du traitement se fait dans de nombreux autres interprètes).
Ainsi, en Jython, lorsque vous compilez votre code Python, vous vous retrouvez avec du code d'octet Java, qui peut être exécuté sur une machine virtuelle Java.
De même, IronPython (écrit en langage C #) compile votre code Python en Common Language Runtime (CLR), qui est une technologie similaire à celle de JVM, développée par Microsoft.