Search code examples
pythonlinuxpython-3.xfedorafedora-25

Python 3.5.0 gives an unexpected magic number


The following code is a part of a linear equation solver. It is written for python 3. Before running the program it checks the magic number from imp.get_magic() against an expected value.

I have Python 3.5.0 installed on a system running Fedora 25. The problem is that, on my system I get a different value for the magic number.

Expected is : b'\xf8\x0c\r\n'

Instead, I get: b'\x16\r\r\n'

Here is the code

def _get_module():
    del globals()['_get_module']
    import imp
    import base64
    import marshal

    magic = imp.get_magic()
    if magic == b'\xf8\x0c\r\n': # Python 3.5
      pycData = <certain value>
    pycData = base64.decodebytes(pycData)

Since I get a different value for the magic number, I can't run this program.

This code is from resources of the book Coding the Matrix. It can be found under the section "The Matrix" and the file is named solver.py (file downloads directly).

Is there a way to get this rolling?


Solution

  • The magic number is updated each time bytecode changes, to make sure that you don't try to load backwards-incompatible bytecode into an older interpreter.

    The specific magic marker that code looks for is the one for Python 3.5a0, see the changelog for markers:

    >>> int.from_bytes(b'\xf8\x0c', 'little')
    3320
    

    while you were trying to load this with 3.5b2 or later (but before 3.5.2):

    >>> int.from_bytes(b'\x16\r', 'little')
    3350
    

    You can just load that version into 3.5.2; just disable the magic marker tests or rework the code to extract the marker (like I did above, first two bytes) and match the maximum possible value.

    I'm not sure why that code is not just distributing a .pyc file in the first place however. Python 3.3 bytecode loads just fine into Python 3.6. I've loaded all versions into Python 3.6, ran dis.dis() on each and found no real differences in the bytecode.