Подтвердить что ты не робот

Являются ли файлы Python 2.5.pyc совместимыми с файлами Python 2.6.pyc?

Некоторое время назад мне пришлось обновить некоторые серверы от 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 и проблема исчезла.

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

Но это может быть плохо для вас, если пользователи с разностными версиями 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 следующим образом:

$ 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'

Ответ 3

Версия 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

Ответ 5

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

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

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