Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to know by which Python version the .pyc file was compiled?

Is there any way to know by which Python version the .pyc file was compiled?

like image 343
Aamir Rind Avatar asked Oct 18 '11 12:10

Aamir Rind


People also ask

What is .PYC file in Python?

pyc files are created by the Python interpreter when a . py file is imported. They contain the "compiled bytecode" of the imported module/program so that the "translation" from source code to bytecode (which only needs to be done once) can be skipped on subsequent imports if the . pyc is newer than the corresponding .

When .PYC file is created?

When a Python source file (module) is imported during an execution for the first time, the appropriate . pyc file is created automatically. If the same module is imported again, then the already created . pyc file is used.

What contains in .PYC file?

pyc file contains the bytecode of your program. We get bytecode after compilation of . py file (source code). . pyc files are not created for all the files that you run.

Where does Python store PYC files?

pyc files are placed in the same directory as the . py file. In Python 3.2, the compiled files are placed in a __pycache__ subdirectory, and are named differently depending on which Python interpreter created them. (This can be useful to people importing the same Python modules from multiple versions of Python.)


3 Answers

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 version Decimal Hexadecimal Comment
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

Sources:

  • Python/import.c - merged by aix from Python 2.7.2 and Python 3.2.2
  • Little endian hex values for comparison first two bytes of Igor Popov's method added by jimbob
like image 96
NPE Avatar answered Oct 16 '22 08:10

NPE


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.

like image 43
Igor Popov Avatar answered Oct 16 '22 08:10

Igor Popov


Or, if you have a GNU/Linux system you can use the command "file" in a terminal:

$ file code.pyc
> code.pyc: python 3.5.2 byte-compiled
like image 16
Tom Avatar answered Oct 16 '22 09:10

Tom