Y a-t-il un moyen de savoir par quelle version de Python le fichier .pyc
a été compilé ?
Réponses
Trop de publicités?Les deux premiers octets du fichier .pyc
sont le nombre magique qui indique la version des bytecodes. Le mot est stocké au format little-endian, et les valeurs connues sont :
# 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)
Vous pouvez obtenir le numéro magique de votre Python comme suit :
$ python -V
Python 2.6.2
# python
>>> import imp
>>> imp.get_magic().encode('hex')
'd1f20d0a'
Pour obtenir le numéro magique d'un fichier pyc, vous pouvez effectuer les opérations suivantes :
>>> f = open('test25.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'b3f20d0a'
>>> f = open('test26.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'd1f20d0a'
En comparant les nombres magiques, vous connaîtrez la version python qui a généré le fichier pyc.
Le dépôt github officiel de Python ne semble plus conserver la liste dans import.c.
Lorsque j'ai cherché une liste plus à jour qu'ailleurs, j'ai rencontré ce qui semble être une liste à jour de Google en mai 2017.
https://github.com/google/pytype/blob/master/pytype/pyc/magic.py