Python Compilation/Interprétation
J'essaie de comprendre le python compilateur/interpréteur de processus plus clairement. Malheureusement, je n'ai pas pris une classe en interprètes et je n'ai pas beaucoup lu sur eux.
Fondamentalement, ce que je comprends est que, actuellement, le code Python de .py fichiers est d'abord compilé en bytecode python (qui je suppose sont la .pyc fichiers je vois de temps en temps?). Ensuite, le pseudo-code est compilé en code machine, une langue que le processeur comprend en fait.
Très jolie, j'ai lu ce fil Pourquoi python compiler le source en bytecode avant d'interpréter?
Quelqu'un pourrait me donner une bonne explication de l'ensemble du processus en gardant à l'esprit que ma connaissance de compilateurs/interpréteurs est presque inexistante? Ou, si cela n'est pas possible, peut-être me donner quelques ressources qui donnent un rapide aperçu des compilateurs/interpréteurs?
Grâce
- Vous n'avez pas "interpréter en code machine" — c'est ce que les compilateurs n'. L'interpréteur Python juste exécute le bytecode. (Et c'est .pyc pour bytecode.)
- Sur une note de côté, vous pourriez trouver utile de savoir que la dernière date de modification de l'original .py fichier est codé dans le .pyc fichier. Cela permet de Python afin de déterminer si une nouvelle .pyc fichier doit être créé ou non. Le but de .pyc fichiers est, bien sûr, afin d'éviter l'analyse de l'ensemble du script à chaque fois que le script est invoqué. Un programme en Python fera pas courir plus vite si l' .pyc est utilisé. Seulement le temps de chargement des changements.
Vous devez vous connecter pour publier un commentaire.
Le bytecode n'est pas réellement interprété en code machine, sauf si vous utilisez exotique de mise en œuvre tels que pypy.
Autre que cela, vous avez la description correcte. Le bytecode est chargé dans l'exécution Python et interprété par une machine virtuelle, qui est un morceau de code qui lit chaque instruction dans le bytecode et exécute toutes les opérations indiquées. Vous pouvez voir ce bytecode avec le
dis
module, comme suit:Explication détaillée
Il est très important de comprendre que le code ci-dessus n'est jamais exécutée par votre CPU; ce n'est jamais transformée en quelque chose qui est (au moins, pas sur l'officiel C mise en œuvre de Python). Le PROCESSEUR exécute le code de la machine virtuelle, qui effectue le travail indiqué par les instructions bytecode. Lorsque l'interprète veut exécuter le
fib
fonction, il lit les instructions une à une, et ne de ce qu'ils disent de faire. Il ressemble à la première instruction,LOAD_FAST 0
, et donc attrape paramètre 0 (len
passé àfib
) à partir de la mesure des paramètres sont détenus et le pousse sur l'interprète de la pile (Python interprète est une pile de la machine). À la lecture de l'instruction suivante,LOAD_CONST 1
, il s'empare de la constante de numéro 1 à partir d'un ensemble de constantes détenue par la fonction, qui se trouve être le numéro 2 dans ce cas, et pousse que sur la pile. Vous pouvez réellement voir ces constantes:La prochaine instruction,
COMPARE_OP 0
, raconte l'interprète de pop les deux de plus en haut de la pile des éléments et effectuer une comparaison de l'inégalité entre eux, poussant le résultat Booléen de retour sur la pile. La quatrième instruction détermine, en fonction de la valeur de type Boolean, que ce soit pour avancer de cinq instructions ou continuer avec la prochaine instruction. Tout ce que verbiage explique leif n < 2
partie de l'expression conditionnelle dansfib
. Il sera très instructif de l'exercice pour vous de démêler le sens et le comportement du reste de lafib
bytecode. Le seul, je ne suis pas sûr à ce sujet estPOP_TOP
; je devineJUMP_IF_FALSE
est défini à quitter son argument Booléen sur la pile plutôt que de les voir apparaître et il a donc ête explicitement.Encore plus instructif est d'inspecter les premières bytecode pour
fib
ainsi:Donc vous pouvez voir que le premier octet de la bytecode est le
LOAD_FAST
instruction. La prochaine paire d'octets,'\x00\x00'
(le nombre 0 à 16 bits) est l'argument deLOAD_FAST
, et indique à l'interpréteur de bytecode à la charge de paramètre 0 sur la pile.case LOAD_FAST:
suivie par le code qui lit les deux octets suivant, regarde le paramètre spécifié dans certains "paramètres" de la collection, et il pousse sur une pile d'objets. Pour interagir avec le monde extérieur, Python permet de faire des appels à des modules d'extension, qui agissent comme des code Python et les objets, mais en réalité le code compilé et peut ainsi parler de cartes graphiques, etc., directement, au nom de votre script(s).GETLOCAL(oparg)
, qui récupère le paramètre correspondant à l'opcode de l'argument dans un local de la variable C, etPUSH(value)
, ce qui pousse le paramètre sur la pile de Python. C'est, essentiellement, LOAD_FAST.co_code
de la fonctionfib
est'|\x00\x00d\x01\x00j\x00\x00o\x05\x00\x01|\x00\x00S\x01t\x00\x00|\x00\x00d\x01\x00\x18\x83\x01\x00t\x00\x00|\x00\x00d\x02\x00\x18\x83\x01\x00\x17S'
l'interpréteur Python pas besoin de module d'importationopcode
puis traduire comme|
àLOAD_FAST
puis faire un peu de l'opération, non? Il vient de faire l'opération quand il lire|
, le moduleopcode
est juste d'aider les gens à unstandingco_code
de la fonction, non?Pour compléter la grande Marcelo Cantos de réponse, voici une petite colonne par colonne, en résumé pour expliquer la sortie de démonté le bytecode.
Par exemple, compte tenu de cette fonction:
Cela peut être démonté en (Python 3.6):
Chaque colonne a un but précis:
JUMP
à partir d'une instruction antérieure à cettedis
module et leur mise en œuvre peut être trouvé dansceval.c
(le cœur de la boucle de Disponible)