Совместимы ли файлы Python 2.5 .pyc с файлами Python 2.6 .pyc? - PullRequest
17 голосов
/ 15 февраля 2010

Некоторое время назад мне пришлось обновить некоторые серверы с Python 2.4 до Python 2.5. Я обнаружил, что файлы .pyc, созданные в Python 2.4, вылетали, когда Python 2.5 пытался их запустить.

Произойдет ли это снова при обновлении с 2.5 до 2.6?

РЕДАКТИРОВАТЬ: Вот немного подробнее

У меня есть файловый сервер, который содержит код Python. Доступ к нему осуществляется как серверами Ubuntu, так и Windows для запуска кода Python. При запуске кода они создают файлы .pyc на файловом сервере.

Я обнаружил, что при обновлении одной из серверных машин с Python 2.4 до 2.5 у меня возникли проблемы с файлами .pyc. Теперь я не уверен, была ли это машина с 2.5, которая пыталась запустить 2.4 байт-код, или это была машина 2.4, которая пыталась запустить 2.5 байт-код, но если я удалил байт-код, все прошло хорошо до следующего столкновения байт-кода.

Я обновил все машины до версии 2.5, и проблема исчезла.

Ответы [ 5 ]

13 голосов
/ 15 февраля 2010

Как правило, .pyc файлы относятся к одной версии Python (хотя переносимы на разные архитектуры компьютеров, если они работают с одной и той же версией); файлы содержат информацию о соответствующей версии Python в своих заголовках - поэтому, если вы оставите соответствующие .py файлы рядом с .pyc, .pyc будет перестраиваться при каждом использовании другой версии Python для импортировать эти модули. «Попытка запустить» файлы неправильной версии .pyc - это то, о чем я никогда не слышал. Какие архитектуры были задействованы? Были ли файлы .py такими, какими они должны быть?

Редактировать : как ОП пояснил, что сбой произошел, когда он запускал программы Python 2.4 и Python 2.5 на одних и тех же файлах .py (с двух разных серверов, общий доступ сетевой диск), объяснение сбоев становится легким. Файлы .py все время перекомпилировались - в Python 2.4, когда 2.5 запускал их совсем недавно, и наоборот - и поэтому файлы .pyc были неистово заняты перезаписью все время. Общеизвестно, что добиться правильной блокировки файлов на сетевых дисках (особенно, но не исключительно в разных операционных системах). Таким образом, должно было произойти следующее (роли могли быть изменены): сервер 2.4 только что определил, что файл .pyc подходит для него, и начал его читать; прежде чем он смог закончить чтение, сервер 2.5 (предварительно определив, что модуль необходимо перекомпилировать) записал поверх него; таким образом, у сервера 2.4 был буфер памяти, который имел (скажем) первые 4 КБ байта из версии 2.4 и следующие 4 КБ из версии 2.5. Тогда использовал этот искаженный буфер, что неудивительно ... крах !!!

Это может быть реальной проблемой, если вы постоянно пытаетесь запустить один набор .py файлов из двух или более разных версий Python (даже на одном и том же сервере, без дополнительных сложностей сетевых дисков). «Правильным» решением будет что-то вроде virtualenv . Хак (простой, но грязный), который мы взяли на работу (много лет назад, но он все еще находится в разработке ...!), Заключается в исправлении каждой версии Python для создания и использования различных расширений для своих скомпилированных файлов байт-кода: .pyc (или .pyo) для Python 1.5.2 (который был самой стабильной "системной" версией, когда мы начали делать этот кладж для более новых версий), .pyc-2.0 для 2.0, .pyc-2.2 для 2.2 и т. Д. (или эквивалент .pyo-X.Y конечно). Я слышал, что это скоро уйдет (спасибо Томасу!), Но на протяжении многих лет мы прилично преодолевали эту щекотливую проблему.

Гораздо более простое решение - сохранить одну версию Python, если это возможно для вашей системы; если в вашей системе есть какие-либо сложности, из-за которых невозможно иметь одну версию Python (как у нас, и у нас), то в эти дни я от всей души рекомендую virtualenv, о котором я уже упоминал.


С принятием PEP 3147 в Python 3.2 файлы pyc для разных версий Python автоматически различаются по имени файла. Это должно решить большинство проблем с разными версиями Python, перезаписывающими файлы pyc друг друга.

5 голосов
/ 15 февраля 2010

Если у вас есть исходный код, он перекомпилирует его для вас. Так что в целом ты в порядке.

Но это может быть плохо для вас, если пользователи с разными версиями Python запускаются из центрального установочного каталога.

Также может быть плохо, если у вас просто есть файлы pyc. Я только что провел быстрый тест для вас. Я создал два .pyc файла. Один в 2,5 и один в 2,6. 2.5 не будет работать в 2.6, а 2.6 не будет работать в 2.5. Оба выдают ошибку «ImportError: Bad magic number in ..», что имеет смысл, поскольку магическое число изменилось с 2,5 до 2,6.

Если вы хотите определить это заранее, вы можете получить магический номер вашего Питона следующим образом:

$ python -V
Python 2.6.2
# python
>>> import imp
>>> imp.get_magic().encode('hex')
'd1f20d0a'

Чтобы получить магическое число для файла pyc, вы можете сделать следующее:

>>> f = open('test25.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'b3f20d0a'
>>> f = open('test26.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'd1f20d0a'
2 голосов
/ 15 февраля 2010

Версия Python, которая создает файл, хранится в самом файле .pyc. Обычно это означает, что файл .pyc заменяется на файл с правильной версией Python

.

некоторые причины, по которым это может не произойти
- разрешения
- .py файл недоступен

В случае проблем с правами доступа Python просто использует .py и игнорирует .pyc (за счет снижения производительности)

Я думаю, что это нормально между второстепенными версиями, хотя, например, Python2.6.2 .pyc должен работать с Python2.6.4

Вот выдержка из / usr / share / file / magic

# python:  file(1) magic for python
0   string      """ a python script text executable
0   belong      0x994e0d0a  python 1.5/1.6 byte-compiled
0   belong      0x87c60d0a  python 2.0 byte-compiled
0   belong      0x2aeb0d0a  python 2.1 byte-compiled
0   belong      0x2ded0d0a  python 2.2 byte-compiled
0   belong      0x3bf20d0a  python 2.3 byte-compiled
0   belong      0x6df20d0a  python 2.4 byte-compiled
0   belong      0xb3f20d0a  python 2.5 byte-compiled
0   belong      0xd1f20d0a  python 2.6 byte-compiled

Итак, вы можете видеть, что правильная версия Python указана первыми 4 байтами файла .pyc

1 голос
/ 11 августа 2010

См. http://www.python.org/dev/peps/pep-3149/ для предлагаемого исправления для этого (возможно в Python 3.2)

0 голосов
/ 15 февраля 2010

Вам, безусловно, нужно будет перекомпилировать файлы байт-кода, чтобы они были полезны. Магическое число байт-кода менялось во всех основных версиях Python (*).

Тем не менее, наличие файлов байт-кода, не соответствующих версии, никогда не должно приводить к сбою Python. Обычно он просто игнорирует любой байт-код, который не имеет правильного номера версии, поэтому не должно быть ошибки, он будет только медленнее в первый раз при перекомпиляции (или медленнее каждый раз, когда пользователь, выполняющий сценарии, не нет прав на запись для обновления байт-кода).

(*: и часто на этапах разработки, плюс в более ранних версиях он иногда также переключался на второстепенные версии. Полный список магических чисел и соответствующих им версий Python см. В import.c .)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...