Is bytecode machine (in)dependent?

Tim Peters tim.peters at gmail.com
Fri Oct 28 12:04:35 EDT 2005


[Robert McLay]
> I'm trying to understand bytecodes generated on different machines.
> I understand that the bytecodes can change between version.  But since
> I'm told that .pyc files are version dependent but not machine
> dependent, I'm wondering why the bytecodes are machine dependent.

They aren't -- at least not particularly <wink>.

> my friend and I created this simple example to explore the problem.
> The example code is:
>
>   #!/usr/bin/env python
>   #
>   import sys, os
>
>   def main():
>     x = 1.234
>     print x
>
>   if ( __name__ == '__main__'):
>     main()
>
>
> Using sib.py from Vendorid 1.0 generates different bytecodes under linux
> and sgi.  At its core sib.py is using:
>
>        # Compile the code using prefix and marshall it.
>        compiled_code = compile(source_code, prefix, 'exec')
>        marshalled_code = marshal.dumps(compiled_code)
>
> to get the bytecodes.

Why do you believe that `prefix` had the same value in both runs?  The
output suggests it did not, but can't guess more than that from here
since I don't know where `prefix` came from.

> So why are the byte codes different?  Is it that the intel-linux is
> little endian and the SGI is big endian

No; marshal format has fixed endianness.

> and the numerical constant (1.234) is stored different depending on the
> endian-ness?

Python defers to the platform C library for string->float conversions,
and it's *possible* that different platforms could convert "1.234" to
a C double in slightly different ways.  There's no evidence of that
here, though.

> This was generated under intel-linux using python 2.4.2
>
>
>
>
>     /*==========================================================================*/
>     /* Frozen main script for test                                              */
>     /* Generated from test.py                                                   */
>     /* This is generated code; Do not modify it!                                */
>     /*--------------------------------------------------------------------------*/
>     unsigned char M___main__[] =
>     {
>         99,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,
>         0,115,55,0,0,0,100,0,0,107,0,0,90,0,0,100,
>         0,0,107,1,0,90,1,0,100,1,0,132,0,0,90,2,
>         0,101,3,0,100,2,0,106,2,0,111,11,0,1,101,2,
>         0,131,0,0,1,110,1,0,1,100,0,0,83,40,3,0,
>         0,0,78,99,0,0,0,0,1,0,0,0,1,0,0,0,
>         67,0,0,0,115,15,0,0,0,100,1,0,125,0,0,124,
>         0,0,71,72,100,0,0,83,40,2,0,0,0,78,102,5,
>         49,46,50,51,52,40,1,0,0,0,116,1,0,0,0,120,
>         40,1,0,0,0,82,0,0,0,0,40,0,0,0,0,40,
>         0,0,0,0,116,23,0,0,0,47,104,111,109,101,47,118,             /* This line */
>         112,97,114,114,47,115,105,98,47,116,101,115,116,46,112,121,
>         116,4,0,0,0,109,97,105,110,5,0,0,0,115,4,0,
>         0,0,0,1,6,1,116,8,0,0,0,95,95,109,97,105,
>         110,95,95,40,4,0,0,0,116,3,0,0,0,115,121,115,
>         116,2,0,0,0,111,115,82,2,0,0,0,116,8,0,0,
>         0,95,95,110,97,109,101,95,95,40,3,0,0,0,82,4,
>         0,0,0,82,2,0,0,0,82,5,0,0,0,40,0,0,
>         0,0,40,0,0,0,0,82,1,0,0,0,116,1,0,0,
>         0,63,3,0,0,0,115,6,0,0,0,18,2,9,4,13,
>         1,
>     };  x
>
>  And under SGI (python 2.4.2) it created :
>
>    /*==========================================================================*/
>    /* Frozen main script for test                                              */
>    /* Generated from test.py                                                   */
>    /* This is generated code; Do not modify it!                                */
>    /*--------------------------------------------------------------------------*/
>    unsigned char M___main__[] =
>    {
>        99,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,
>        0,115,55,0,0,0,100,0,0,107,0,0,90,0,0,100,
>        0,0,107,1,0,90,1,0,100,1,0,132,0,0,90,2,
>        0,101,3,0,100,2,0,106,2,0,111,11,0,1,101,2,
>        0,131,0,0,1,110,1,0,1,100,0,0,83,40,3,0,
>        0,0,78,99,0,0,0,0,1,0,0,0,1,0,0,0,
>        67,0,0,0,115,15,0,0,0,100,1,0,125,0,0,124,
>        0,0,71,72,100,0,0,83,40,2,0,0,0,78,102,5,
>        49,46,50,51,52,40,1,0,0,0,116,1,0,0,0,120,
>        40,1,0,0,0,82,0,0,0,0,40,0,0,0,0,40,
>        0,0,0,0,116,23,0,0,0,47,87,111,114,107,47,118,              /* This line */
>        112,97,114,114,47,115,105,98,47,116,101,115,116,46,112,121,
>        116,4,0,0,0,109,97,105,110,5,0,0,0,115,4,0,
>        0,0,0,1,6,1,116,8,0,0,0,95,95,109,97,105,
>        110,95,95,40,4,0,0,0,116,3,0,0,0,115,121,115,
>        116,2,0,0,0,111,115,82,2,0,0,0,116,8,0,0,
>        0,95,95,110,97,109,101,95,95,40,3,0,0,0,82,4,
>        0,0,0,82,2,0,0,0,82,5,0,0,0,40,0,0,
>        0,0,40,0,0,0,0,82,1,0,0,0,116,1,0,0,
>        0,63,3,0,0,0,115,6,0,0,0,18,2,9,4,13,
>        1,
>    };
>
>
> The difference between the two is very slight:
>
> 18c18
> <     0,0,0,0,116,23,0,0,0,47,104,111,109,101,47,118,
> ---
> >     0,0,0,0,116,23,0,0,0,47,87,111,114,107,47,118,

Stare at this:

>>> ''.join(map(chr, [47,104,111,109,101,47,118]))
'/home/v'
>>> ''.join(map(chr, [47,87,111,114,107,47,118]))
'/Work/v'

It _suggests_ that `prefix` contained the substring "/home/" on one
box but ""/Work/" on the other.



More information about the Python-list mailing list