modulos - Si se interpreta Python, ¿qué son los archivos.pyc?
paquetes de python (9)
Me han dado a entender que Python es un lenguaje interpretado ...
Este meme popular es incorrecto, o, más bien, se basa en una mala interpretación de los niveles del lenguaje (natural): un error similar sería decir "la Biblia es un libro de tapa dura". Déjame explicarte ese símil ...
"La Biblia" es "un libro" en el sentido de ser una clase de (objetos físicos reales identificados como) libros; se supone que los libros identificados como "copias de la Biblia" tienen algo fundamental en común (los contenidos, aunque incluso pueden estar en diferentes idiomas, con diferentes traducciones aceptables, niveles de notas al pie y otras anotaciones), sin embargo, esos libros son perfectamente bien permitido diferir en una gran variedad de aspectos que no se consideran fundamentales: tipo de encuadernación, color de encuadernación, fuente (s) utilizada (s) en la impresión, ilustraciones en su caso, márgenes amplios o no, números y tipos de marcadores incorporados , y así sucesivamente y así sucesivamente.
Es muy posible que una impresión típica de la Biblia sea en una encuadernación de tapa dura; después de todo, es un libro que normalmente debe leerse una y otra vez, marcado en varios lugares, hojeado en busca de determinados punteros de capítulo y verso , etc., etc., y una buena encuadernación de tapa dura puede hacer que una copia dada dure más bajo dicho uso. Sin embargo, estos son problemas mundanos (prácticos) que no se pueden usar para determinar si un objeto de libro real dado es una copia de la Biblia o no: ¡las impresiones en rústica son perfectamente posibles!
De manera similar, Python es "un lenguaje" en el sentido de definir una clase de implementaciones de lenguaje que deben ser todas similares en algunos aspectos fundamentales (sintaxis, la mayoría de las semánticas, excepto aquellas partes en las que se permite explícitamente que difieran), pero están totalmente permitidas difieren en casi todos los detalles de la "implementación", incluida la forma en que manejan los archivos de origen que reciben, si compilan los orígenes en algunos formularios de nivel inferior (y, si es así, qué formulario) y si guardan tal información formas compiladas, en disco o en otro lugar), cómo ejecutan dichas formas, etc.
La implementación clásica, CPython, a menudo se llama simplemente "Python" para abreviar, pero es solo una de varias implementaciones de calidad de producción, junto con IronPython de Microsoft (que se compila a los códigos CLR, es decir, ".NET"), Jython (que se compila a los códigos JVM), PyPy (que está escrito en Python y puede compilarse en una gran variedad de formularios "back-end", incluido el lenguaje de máquina generado "justo a tiempo"). Todos ellos son Python (== "implementaciones del lenguaje Python") al igual que muchos objetos de libros superficialmente diferentes pueden ser Biblias (== "copias de La Biblia").
Si está interesado específicamente en CPython: compila los archivos de origen en un formulario de nivel inferior específico de Python (conocido como "bytecode"), lo hace automáticamente cuando es necesario (cuando no hay ningún archivo de bytecode correspondiente a un archivo de origen, o el archivo de bytecode es más antiguo que el origen o compilado por una versión diferente de Python), generalmente guarda los archivos de bytecode en el disco (para evitar volver a compilarlos en el futuro). OTOH IronPython generalmente compilará en códigos CLR (guardándolos en el disco o no, dependiendo) y Jython en códigos JVM (guardándolos en el disco o no; utilizará la extensión .class
si los guarda).
Estas formas de nivel inferior se ejecutan mediante "máquinas virtuales" apropiadas, también conocidas como "intérpretes": CPython VM, .Net runtime, Java VM (también conocida como JVM), según corresponda.
Entonces, en este sentido (¿qué hacen las implementaciones típicas), Python es un "lenguaje interpretado" si y solo si C # y Java son: todos ellos tienen una estrategia de implementación típica de producir primero el código bytecode, luego ejecutarlo a través de una VM / intérprete? .
Lo más probable es que el enfoque se centre en cómo el proceso de compilación es "pesado", lento y de alto nivel. CPython está diseñado para compilar lo más rápido posible, lo más liviano posible, con la menor ceremonia posible: el compilador realiza muy pocas comprobaciones de errores y optimización, por lo que puede ejecutarse con rapidez y en pequeñas cantidades de memoria, lo que a su vez lo permite ejecutarse de forma automática y transparente siempre que sea necesario, sin que el usuario tenga que estar consciente de que hay una compilación en funcionamiento la mayor parte del tiempo. Java y C # generalmente aceptan más trabajo durante la compilación (y, por lo tanto, no realizan la compilación automática) para verificar los errores más a fondo y realizar más optimizaciones. Es un continuo de escalas de grises, no una situación blanca o negra, y sería completamente arbitrario poner un umbral en un nivel dado y decir que solo por encima de ese nivel lo llamas "compilación".
Me han dado a entender que Python es un lenguaje interpretado ... Sin embargo, cuando miro el código fuente de Python, veo archivos .pyc
, que Windows identifica como "Archivos de Python compilados". ¿Dónde vienen estos?
Contienen código de bytes , que es lo que el intérprete de Python compila la fuente. Este código es ejecutado por la máquina virtual de Python.
La documentación de Python explica la definición de esta manera:
Python es un lenguaje interpretado, a diferencia de uno compilado, aunque la distinción puede ser borrosa debido a la presencia del compilador de bytecode. Esto significa que los archivos de origen se pueden ejecutar directamente sin crear explícitamente un ejecutable que luego se ejecuta.
El archivo * .py de Python es solo un archivo de texto en el que escribes algunas líneas de código. Cuando intente ejecutar este archivo, diga "python filename.py"
Este comando invoca la máquina virtual de Python. La máquina virtual de Python tiene 2 componentes: "compilador" e "intérprete". El intérprete no puede leer directamente el texto en el archivo * .py, por lo que este texto se convierte primero en un código de byte que está dirigido al PVM (no al hardware sino al PVM) . PVM ejecuta este código de byte. También se genera el archivo * .pyc, como parte de la ejecución que realiza la operación de importación en el archivo en shell o en algún otro archivo.
Si este archivo * .pyc ya está generado, la próxima vez que ejecute / ejecute su archivo * .py, el sistema cargará directamente su archivo * .pyc, que no necesitará ninguna compilación (esto le ahorrará algunos ciclos de procesador en la máquina).
Una vez que se genera el archivo * .pyc, no es necesario el archivo * .py, a menos que lo edite.
El código de Python pasa por 2 etapas. El primer paso compila el código en archivos .pyc, que en realidad es un código de bytes. Luego, este archivo .pyc (código de bytes) se interpreta utilizando el intérprete CPython. Por favor, consulte this enlace. Aquí el proceso de compilación y ejecución del código se explica en términos sencillos.
Estos son creados por el intérprete de Python cuando se importa un archivo .py
, y contienen el "bytecode compilado" del módulo / programa importado, con la idea de que la "traducción" del código fuente al bytecode (que solo debe hacerse) una vez) se puede omitir en las import
posteriores si .pyc
es más nuevo que el archivo .py
correspondiente, lo que acelera un poco el inicio. Pero todavía se interpreta.
No existe tal cosa como un lenguaje interpretado. Si se utiliza un intérprete o un compilador es simplemente un rasgo de la implementación y no tiene absolutamente nada que ver con el lenguaje.
Cada idioma puede ser implementado por un intérprete o un compilador. La gran mayoría de los idiomas tienen al menos una implementación de cada tipo. (Por ejemplo, hay intérpretes para C y C ++ y compiladores para JavaScript, PHP, Perl, Python y Ruby). Además, la mayoría de las implementaciones de lenguaje moderno en realidad combinan un intérprete y un compilador (o incluso varios compiladores).
Un lenguaje es solo un conjunto de reglas matemáticas abstractas. Un intérprete es una de varias estrategias de implementación concretas para un idioma. Esos dos viven en niveles de abstracción completamente diferentes. Si el inglés fuera un idioma escrito, el término "lenguaje interpretado" sería un error de tipo. La declaración "Python es un lenguaje interpretado" no es simplemente falsa (porque ser falso implicaría que la declaración tiene sentido, incluso si es incorrecta), simplemente no tiene sentido , porque un lenguaje nunca puede definirse como "interpretado."
En particular, si observa las implementaciones existentes de Python, estas son las estrategias de implementación que están utilizando:
- IronPython: compila en árboles DLR que el DLR luego compila en el bytecode CIL. Lo que suceda con el código de bytes de CIL dependerá del CLI VES en el que se ejecute, pero Microsoft .NET, GNU Portable.NET y Novell Mono eventualmente lo compilarán en un código de máquina nativo.
- Jython: interpreta el código fuente de Python hasta que identifica las rutas de código activo, que luego compila en el bytecode JVML. Lo que suceda con el código de bytes JVML depende de la JVM en la que se ejecute. Maxine lo compilará directamente en un código nativo no optimizado hasta que identifique las rutas del código activo, que luego compila al código nativo optimizado. HotSpot interpretará primero el código de bytes JVML y luego compilará las rutas del código activo a un código de máquina optimizado.
- PyPy: se compila en el bytecode de PyPy, que luego es interpretado por la máquina virtual de PyPy hasta que identifica las rutas de código activo que luego compila en el código nativo, el bytecode JVML o el bytecode CIL, según la plataforma en la que se esté ejecutando.
- CPython: compila en el bytecode CPython que luego interpreta.
- Python sin pila: se compila en el bytecode CPython que luego interpreta.
- Unladen Swallow: se compila en el bytecode CPython que luego interpreta hasta que identifica las rutas de código hot que luego compila en LLVM IR, que el compilador LLVM luego compila en el código de máquina nativo.
Puede notar que cada una de las implementaciones en esa lista (además de algunas otras que no mencioné, como Tinypy, Shedskin o Psyco) tiene un compilador. De hecho, hasta donde sé, actualmente no hay una implementación de Python que se interprete de manera pura, no hay tal implementación planeada y nunca ha habido tal implementación.
No solo el término "lenguaje interpretado" no tiene sentido, incluso si lo interpreta como que significa "lenguaje con implementación interpretada", claramente no es cierto. Quien te haya dicho eso, obviamente no sabe de qué está hablando.
En particular, los archivos .pyc
que está viendo son archivos de código de bytes almacenados en caché producidos por CPython, Stackless Python o Unladen Swallow.
Para acelerar la carga de módulos, Python almacena en caché el contenido compilado de los módulos en .pyc.
CPython compila su código fuente en "código de bytes" y, por razones de rendimiento, almacena este código de bytes en el sistema de archivos cada vez que el archivo de origen tiene cambios. Esto hace que la carga de módulos Python sea mucho más rápida porque la fase de compilación se puede omitir. Cuando su archivo fuente es foo.py, CPython almacena en caché el código de byte en un archivo foo.pyc justo al lado de la fuente.
En Python3, la maquinaria de importación de Python se extiende para escribir y buscar archivos de caché de código byte en un solo directorio dentro de cada directorio de paquetes de Python. Este directorio se llamará __pycache__.
Aquí hay un diagrama de flujo que describe cómo se cargan los módulos:
Para más información:
ref: PEP3147
ref: archivos de Python "compilados"
Python (al menos su implementación más común) sigue un patrón de compilación de la fuente original a los códigos de bytes, y luego interpreta los códigos de bytes en una máquina virtual. Esto significa (una vez más, la implementación más común) no es un intérprete puro ni un compilador puro.
Sin embargo, el otro lado de esto es que el proceso de compilación está mayormente oculto: los archivos .pyc se tratan básicamente como un caché; aceleran las cosas, pero normalmente no tienes que ser consciente de ellas en absoluto. Automáticamente los invalida y los vuelve a cargar (vuelve a compilar el código fuente) cuando es necesario en función de las marcas de fecha / hora del archivo.
Casi la única vez que he visto un problema con esto fue cuando un archivo de código de bytes compilado de alguna manera obtuvo una marca de tiempo en el futuro, lo que significaba que siempre parecía más nuevo que el archivo de origen. Como parecía más nuevo, el archivo de origen nunca se volvió a compilar, por lo que no importa qué cambios haya realizado, se ignoraron ...
ESTO ES PARA PRINCIPIANTES,
Python compila automáticamente su script a código compilado, llamado código byte, antes de ejecutarlo.
La ejecución de un script no se considera una importación y no se creará .pyc.
Por ejemplo, si tiene un archivo de script abc.py que importa otro módulo xyz.py , cuando ejecute abc.py , se creará xyz.pyc , ya que xyz se importará, pero no se creará ningún archivo abc.pyc desde abc. Py no está siendo importado.
Si necesita crear un archivo .pyc para un módulo que no se importa, puede usar los módulos py_compile
y compileall
.
El módulo py_compile
puede compilar manualmente cualquier módulo. Una forma es usar la función py_compile.compile
en ese módulo de manera interactiva:
>>> import py_compile
>>> py_compile.compile(''abc.py'')
Esto escribirá el .pyc en la misma ubicación que abc.py (puede anularlo con el parámetro opcional cfile
).
También puede compilar automáticamente todos los archivos en un directorio o directorios utilizando el módulo compileall.
python -m compileall
Si se omite el nombre del directorio (el directorio actual en este ejemplo), el módulo compila todo lo que se encuentra en sys.path