Last active
May 20, 2024 04:22
-
-
Save delimitry/bad5496b52161449f6de to your computer and use it in GitHub Desktop.
Get the version of Python by which the file was compiled
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
A script to get the version of Python by which the file was compiled | |
""" | |
from __future__ import print_function | |
import binascii | |
import os | |
import sys | |
import struct | |
MAGICS = { | |
20121: 'Python 1.5.x', | |
50428: 'Python 1.6', | |
50823: 'Python 2.0.x', | |
60202: 'Python 2.1.x', | |
60717: 'Python 2.2', | |
62011: 'Python 2.3a0', | |
62021: 'Python 2.3a0', | |
62041: 'Python 2.4a0', | |
62051: 'Python 2.4a3', | |
62061: 'Python 2.4b1', | |
62071: 'Python 2.5a0', | |
62081: 'Python 2.5a0', | |
62091: 'Python 2.5a0', | |
62092: 'Python 2.5a0', | |
62101: 'Python 2.5b3', | |
62111: 'Python 2.5b3', | |
62121: 'Python 2.5c1', | |
62131: 'Python 2.5c2', | |
62151: 'Python 2.6a0', | |
62161: 'Python 2.6a1', | |
62171: 'Python 2.7a0', | |
62181: 'Python 2.7a0', | |
62191: 'Python 2.7a0', | |
62201: 'Python 2.7a0', | |
62211: 'Python 2.7a0', | |
3000: 'Python 3000', | |
3010: 'Python 3000', | |
3020: 'Python 3000', | |
3030: 'Python 3000', | |
3040: 'Python 3000', | |
3050: 'Python 3000', | |
3060: 'Python 3000', | |
3061: 'Python 3000', | |
3071: 'Python 3000', | |
3081: 'Python 3000', | |
3091: 'Python 3000', | |
3101: 'Python 3000', | |
3103: 'Python 3000', | |
3111: 'Python 3.0a4', | |
3131: 'Python 3.0b1', | |
3141: 'Python 3.1a1', | |
3151: 'Python 3.1a1', | |
3160: 'Python 3.2a1', | |
3170: 'Python 3.2a2', | |
3180: 'Python 3.2a3', | |
3190: 'Python 3.3a1', | |
3200: 'Python 3.3a1', | |
3210: 'Python 3.3a1', | |
3220: 'Python 3.3a2', | |
3230: 'Python 3.3a4', | |
3250: 'Python 3.4a1', | |
3260: 'Python 3.4a1', | |
3270: 'Python 3.4a1', | |
3280: 'Python 3.4a1', | |
3290: 'Python 3.4a4', | |
3300: 'Python 3.4a4', | |
3310: 'Python 3.4rc2', | |
3320: 'Python 3.5a1', | |
3330: 'Python 3.5b1', | |
3340: 'Python 3.5b2', | |
3350: 'Python 3.5b3', | |
3351: 'Python 3.5.2', | |
3360: 'Python 3.6a0', | |
3361: 'Python 3.6a1', | |
3370: 'Python 3.6a2', | |
3371: 'Python 3.6a2', | |
3372: 'Python 3.6a2', | |
3373: 'Python 3.6b1', | |
3375: 'Python 3.6b1', | |
3376: 'Python 3.6b1', | |
3377: 'Python 3.6b1', | |
3378: 'Python 3.6b2', | |
3379: 'Python 3.6rc1', | |
3390: 'Python 3.7a1', | |
3391: 'Python 3.7a2', | |
3392: 'Python 3.7a4', | |
3393: 'Python 3.7b1', | |
3394: 'Python 3.7b5', | |
3400: 'Python 3.8a1', | |
3401: 'Python 3.8a1', | |
3410: 'Python 3.8a1', | |
3411: 'Python 3.8b2', | |
3412: 'Python 3.8b2', | |
3413: 'Python 3.8b4', | |
3420: 'Python 3.9a0', | |
3421: 'Python 3.9a0', | |
3422: 'Python 3.9a0', | |
3423: 'Python 3.9a2', | |
3424: 'Python 3.9a2', | |
3425: 'Python 3.9a2', | |
3430: 'Python 3.10a1', | |
3431: 'Python 3.10a1', | |
3432: 'Python 3.10a2', | |
3433: 'Python 3.10a2', | |
3434: 'Python 3.10a6', | |
3435: 'Python 3.10a7', | |
3436: 'Python 3.10b1', | |
3437: 'Python 3.10b1', | |
3438: 'Python 3.10b1', | |
3439: 'Python 3.10b1', | |
3450: 'Python 3.11a1', | |
3451: 'Python 3.11a1', | |
3452: 'Python 3.11a1', | |
3453: 'Python 3.11a1', | |
3454: 'Python 3.11a1', | |
3455: 'Python 3.11a1', | |
3456: 'Python 3.11a1', | |
3457: 'Python 3.11a1', | |
3458: 'Python 3.11a1', | |
3459: 'Python 3.11a1', | |
3460: 'Python 3.11a1', | |
3461: 'Python 3.11a1', | |
3462: 'Python 3.11a2', | |
3463: 'Python 3.11a3', | |
3464: 'Python 3.11a3', | |
3465: 'Python 3.11a3', | |
3466: 'Python 3.11a4', | |
3467: 'Python 3.11a4', | |
3468: 'Python 3.11a4', | |
3469: 'Python 3.11a4', | |
3470: 'Python 3.11a4', | |
3471: 'Python 3.11a4', | |
3472: 'Python 3.11a4', | |
3473: 'Python 3.11a4', | |
3474: 'Python 3.11a4', | |
3475: 'Python 3.11a5', | |
3476: 'Python 3.11a5', | |
3477: 'Python 3.11a5', | |
3478: 'Python 3.11a5', | |
3479: 'Python 3.11a5', | |
3480: 'Python 3.11a5', | |
3481: 'Python 3.11a5', | |
3482: 'Python 3.11a5', | |
3483: 'Python 3.11a5', | |
3484: 'Python 3.11a5', | |
3485: 'Python 3.11a5', | |
3486: 'Python 3.11a6', | |
3487: 'Python 3.11a6', | |
3488: 'Python 3.11a6', | |
3489: 'Python 3.11a6', | |
3490: 'Python 3.11a6', | |
3491: 'Python 3.11a6', | |
3492: 'Python 3.11a7', | |
3493: 'Python 3.11a7', | |
3494: 'Python 3.11a7', | |
3495: 'Python 3.11b4', | |
3500: 'Python 3.12a1', | |
3501: 'Python 3.12a1', | |
3502: 'Python 3.12a1', | |
3503: 'Python 3.12a1', | |
3504: 'Python 3.12a1', | |
3505: 'Python 3.12a1', | |
3506: 'Python 3.12a1', | |
3507: 'Python 3.12a1', | |
3508: 'Python 3.12a1', | |
3509: 'Python 3.12a1', | |
3510: 'Python 3.12a2', | |
3511: 'Python 3.12a2', | |
3512: 'Python 3.12a2', | |
3513: 'Python 3.12a4', | |
3514: 'Python 3.12a4', | |
3515: 'Python 3.12a5', | |
3516: 'Python 3.12a5', | |
3517: 'Python 3.12a5', | |
3518: 'Python 3.12a6', | |
3519: 'Python 3.12a6', | |
3520: 'Python 3.12a6', | |
3521: 'Python 3.12a7', | |
3522: 'Python 3.12a7', | |
3523: 'Python 3.12a7', | |
3524: 'Python 3.12a7', | |
3525: 'Python 3.12b1', | |
3526: 'Python 3.12b1', | |
3527: 'Python 3.12b1', | |
3528: 'Python 3.12b1', | |
3529: 'Python 3.12b1', | |
3530: 'Python 3.12b1', | |
3531: 'Python 3.12b1', | |
3550: 'Python 3.13a1', | |
3551: 'Python 3.13a1', | |
3552: 'Python 3.13a1', | |
3553: 'Python 3.13a1', | |
3554: 'Python 3.13a1', | |
3555: 'Python 3.13a1', | |
3556: 'Python 3.13a1', | |
3557: 'Python 3.13a1', | |
3558: 'Python 3.13a1', | |
3559: 'Python 3.13a1', | |
3560: 'Python 3.13a1', | |
3561: 'Python 3.13a1', | |
3562: 'Python 3.13a1', | |
3563: 'Python 3.13a1', | |
3564: 'Python 3.13a1', | |
3565: 'Python 3.13a1', | |
3566: 'Python 3.13a1', | |
3567: 'Python 3.13a1', | |
3568: 'Python 3.13a1', | |
} | |
def get_compiled_file_python_version(filename): | |
"""Get the version of Python by which the file was compiled""" | |
ext = os.path.splitext(filename)[1] | |
if ext not in ['.pyc', '.pyo']: | |
print('Please select *.pyc or *.pyo files') | |
return '' | |
if not os.path.isfile(filename): | |
print('File "%s" doesn\'t exist' % filename) | |
return '' | |
with open(filename, 'rb') as in_file: | |
magic = in_file.read(4) | |
magic_data = struct.unpack('H2B', magic) | |
python_version = MAGICS.get(magic_data[0], '') | |
if magic_data[1:] != (13, 10): | |
magic_hex = binascii.hexlify(magic).decode() | |
print('Wrong magic bytes "%s". Last two bytes must be "0d0a"!' % magic_hex) | |
return '' | |
if not python_version: | |
print('Unknown Python version or wrong magic bytes!') | |
return python_version | |
def main(): | |
"""Main""" | |
if len(sys.argv) < 2: | |
sys.exit('Usage: %s <file>' % os.path.basename(sys.argv[0])) | |
filename = sys.argv[1] | |
python_version = get_compiled_file_python_version(filename) | |
if python_version: | |
print('File "%s" is compiled with: %s' % (filename, python_version)) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Suggested changes (incl. typo fix):
https://gist.githubusercontent.com/helix84/f14b5516ea501ee220013d7a63db560b/raw/2a037242015bcd747f6b8e501d425dfbed2b20d0/compiled_file_python_version.py