You can get the magic number of your Python as follows:
$ python -V
Python 2.6.2
# python
>>> import imp
>>> imp.get_magic().encode('hex')
'd1f20d0a'
To get the magic number for a pyc file you can do the following:
>>> f = open('test25.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'b3f20d0a'
>>> f = open('test26.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'd1f20d0a'
By comparing the magic numbers you'll know the python version that generated the pyc file.
The first two bytes of the .pyc
file are the magic number that tells the version of the bytecodes. The word is stored in little-endian format, and the known values are:
# Python/import.c - merged by aix from Python 2.7.2 and Python 3.2.2
# EDIT: added little endian hex values for comparison first two bytes of Igor Popov's method -jimbob
Python 1.5: 20121 0x994e
Python 1.5.1: 20121 0x994e
Python 1.5.2: 20121 0x994e
Python 1.6: 50428 0x4cc4
Python 2.0: 50823 0x87c6
Python 2.0.1: 50823 0x87c6
Python 2.1: 60202 0x2aeb
Python 2.1.1: 60202 0x2aeb
Python 2.1.2: 60202 0x2aeb
Python 2.2: 60717 0x2ded
Python 2.3a0: 62011 0x3bf2
Python 2.3a0: 62021 0x45f2
Python 2.3a0: 62011 0x3bf2 (!)
Python 2.4a0: 62041 0x59f2
Python 2.4a3: 62051 0x63f2
Python 2.4b1: 62061 0x6df2
Python 2.5a0: 62071 0x77f2
Python 2.5a0: 62081 0x81f2 (ast-branch)
Python 2.5a0: 62091 0x8bf2 (with)
Python 2.5a0: 62092 0x8cf2 (changed WITH_CLEANUP opcode)
Python 2.5b3: 62101 0x95f2 (fix wrong code: for x, in ...)
Python 2.5b3: 62111 0x9ff2 (fix wrong code: x += yield)
Python 2.5c1: 62121 0xa9f2 (fix wrong lnotab with for loops and
storing constants that should have been removed)
Python 2.5c2: 62131 0xb3f2 (fix wrong code: for x, in ... in listcomp/genexp)
Python 2.6a0: 62151 0xc7f2 (peephole optimizations and STORE_MAP opcode)
Python 2.6a1: 62161 0xd1f2 (WITH_CLEANUP optimization)
Python 2.7a0: 62171 0xdbf2 (optimize list comprehensions/change LIST_APPEND)
Python 2.7a0: 62181 0xe5f2 (optimize conditional branches:
introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE)
Python 2.7a0 62191 0xeff2 (introduce SETUP_WITH)
Python 2.7a0 62201 0xf9f2 (introduce BUILD_SET)
Python 2.7a0 62211 0x03f3 (introduce MAP_ADD and SET_ADD)
Python 3000: 3000 0xb80b
3010 0xc20b (removed UNARY_CONVERT)
3020 0xcc0b (added BUILD_SET)
3030 0xd60b (added keyword-only parameters)
3040 0xe00b (added signature annotations)
3050 0xea0b (print becomes a function)
3060 0xf40b (PEP 3115 metaclass syntax)
3061 0xf50b (string literals become unicode)
3071 0xff0b (PEP 3109 raise changes)
3081 0x090c (PEP 3137 make __file__ and __name__ unicode)
3091 0x130c (kill str8 interning)
3101 0x1d0c (merge from 2.6a0, see 62151)
3103 0x1f0c (__file__ points to source file)
Python 3.0a4: 3111 0x270c (WITH_CLEANUP optimization).
Python 3.0a5: 3131 0x3b0c (lexical exception stacking, including POP_EXCEPT)
Python 3.1a0: 3141 0x450c (optimize list, set and dict comprehensions:
change LIST_APPEND and SET_ADD, add MAP_ADD)
Python 3.1a0: 3151 0x4f0c (optimize conditional branches:
introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE)
Python 3.2a0: 3160 0x580c (add SETUP_WITH)
tag: cpython-32
Python 3.2a1: 3170 0x620c (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR)
tag: cpython-32
Python 3.2a2 3180 0x6c0c (add DELETE_DEREF)
Take a look at my script in Python that detects and returns the version of Python by which the file (*.pyc or *.pyo) was compiled.
It detects versions of Python from Python 1.5 up to Python 3.5a0.