En general, .pyc
los archivos son específicos de una versión de Python (aunque son portátiles en diferentes arquitecturas de máquina, siempre que ejecuten la misma versión); los archivos llevan la información sobre la versión de Python relevante en sus encabezados, por lo que si deja los archivos correspondientes .py
junto a los .pyc
, se reconstruirá el .pyc
cada vez que se use una versión de Python diferente para importar esos módulos."Intentar ejecutar" archivos de la versión incorrecta .pyc
es algo de lo que nunca había oído hablar. ¿Qué arquitecturas estuvieron involucradas? ¿Los archivos .py
estaban como deberían?
Editar: como el OP aclaró que los choques se produjo cuando estaba corriendo tanto Python 2.4 y Python 2.5 programas en el mismo .py
archivos (desde dos servidores diferentes, que comparten una unidad de red), la explicación de la los accidentes se vuelven fáciles. Los archivos .py
fueron recompilados todo el tiempo - por el 2.4 Python cuando el 2.5 había sido el que los ejecutaba más recientemente, y viceversa - y por lo tanto los archivos .pyc
estaban frenéticamente ocupados y se reescribían todo el tiempo. El bloqueo adecuado de archivos en unidades de red (especialmente, pero no exclusivamente, en diferentes sistemas operativos) es notoriamente difícil de lograr. Entonces debe haber sucedido lo siguiente (los roles podrían cambiarse): el servidor 2.4 acababa de determinar que un archivo .pyc
estaba bien para él y comenzó a leerlo; antes de que pudiera terminar de leer, el servidor 2.5 (habiendo determinado previamente que el módulo necesitaba ser recompilado) escribió sobre él; por lo que el servidor 2.4 terminó con un búfer de memoria que tenía (digamos) los primeros 4K bytes de la versión 2.4 y los siguientes 4K bytes de la versión 2.5. Cuando entonces usó ese búfer destrozado, como era de esperar ... crash !!!
Esto puede ser un problema real si alguna vez continuamente intenta ejecutar un solo conjunto de archivos .py
de dos o más versiones diferentes de Python (incluso en el mismo servidor, sin las complicaciones adicionales de las unidades de red). La solución "adecuada" sería algo así como virtualenv. El truco (simple, pero sucio) que adoptamos en el trabajo (hace muchos años, pero todavía está en producción ...!) Es parchear cada versión de Python para producir y usar una extensión diferente para sus archivos de códigos de bytes compilados: .pyc
(o .pyo
) para Python 1.5.2
(que era la versión más estable del "sistema" cuando comenzamos a hacer esto kludge a versiones más nuevas), .pyc-2.0
para 2.0, .pyc-2.2
para 2.2, y así sucesivamente (o equivalente .pyo-X.Y
por supuesto). He oído que esto pronto va a desaparecer por fin (gracias Thomas! -), pero nos mareó semi-decentemente sobre este problema cosquilloso durante muchos, muchos años.
Una solución mucho más simple es mantener una sola versión de Python, si eso es factible para su sistema; Si su sistema tiene alguna complicación que lo haga inviable de tener una sola versión de Python (como la nuestra, y lo hace), entonces en estos días recomiendo encarecidamente virtualenv
, que ya he mencionado.
A veces las personas intentan distribuir archivos .pyc sin archivos .py como una forma de protección de IP. –
@gnibbler: Sí, pero eso es estúpido, ya que los archivos .pyc son muy legibles y fáciles de descompilar para una representación muy cercana – nosklo
Gracias por eso. Estoy sorprendido por el error de bloqueo de archivos. Eso significa que no puedo actualizar desde Python 2.5 a 2.6 un servidor a la vez, pero tengo que bajarlos y actualizarlos todos antes de volverlos a subir. – pwdyson