Skip to main content

Python cross-version byte-code interpeter

Project description

TravisCI CircleCI

x-python

This is a CPython bytecode interpreter written Python.

You can use this to:

  • Learn about how the internals of CPython works since this models that

  • Use as a sandboxed environment for trying pieces of execution

  • Have one Python program that runs multiple versions of Python bytecode. For a number of things you can Python 2.5 or 2.6 bytecode from inside Python 3.7; No need to install Python 2.5 or 2.6!

  • Use in a dynamic fuzzer or in coholic execution for analysis

The sandboxed environment in a debugger I find interesting. Since there is a separate execution, and traceback stack, inside a debugger you can try things out in the middle of a debug session without effecting the real execution. On the other hand if a sequence of executions works out, it is possible to copy this (under certain circumstances) back into CPython’s execution stack.

Going the other way, I may at some point hook in my debugger into this interpreter and then you’ll have a conventional pdb/gdb like debugger also with the ability to step bytecode instructions.

Another unexplored avenue implied above is mixing interpretation and direct CPython execution. In fact, there are bugs so this happens right now, but it will be turned into a feature. Some functions or classes you may want to not run under a slow interpreter while others you do want to run under the interpreter.

Examples:

What to know instructions get run when you write some simple code? Try this:

$ xpython -vc "x, y = 2, 3; x **= y"
INFO:xpython.pyvm2:Line    1,   0: LOAD_CONST (2, 3)
INFO:xpython.pyvm2:             2: UNPACK_SEQUENCE 2
INFO:xpython.pyvm2:             4: STORE_NAME 'x'
INFO:xpython.pyvm2:             6: STORE_NAME 'y'
INFO:xpython.pyvm2:             8: LOAD_NAME 'x'
INFO:xpython.pyvm2:            10: LOAD_NAME 'y'
INFO:xpython.pyvm2:            12: INPLACE_POWER
INFO:xpython.pyvm2:            14: STORE_NAME 'x'
INFO:xpython.pyvm2:            16: LOAD_CONST None
INFO:xpython.pyvm2:            18: RETURN_VALUE

Option -c is the same as Python’s flag (program passed in as string) and -v is also analogus Python’s flag. Here, it shows the bytecode instructions run.

Want the execution stack stack and block stack in addition? Add another v:

$ xpython -vvc "x, y = 2, 3; x **= y"
DEBUG:xpython.pyvm2:make_frame: code=<code object <module> at 0x7f33d1cf01e0, file "<string x, y = 2, 3; x **= y>", line 1>, callargs={}, f_globals=(<class 'dict'>, 139860540041568), f_locals=(<class 'NoneType'>, 94796399066560)
DEBUG:xpython.pyvm2:<Frame at 0x7f33d135ef50: '<string x, y = 2, 3; x **= y>' @ 1>
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:Line    1,   0: LOAD_CONST (2, 3)
DEBUG:xpython.pyvm2:  frame.stack: [(2, 3)]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             2: UNPACK_SEQUENCE 2
DEBUG:xpython.pyvm2:  frame.stack: [3, 2]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             4: STORE_NAME 'x'
DEBUG:xpython.pyvm2:  frame.stack: [3]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             6: STORE_NAME 'y'
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             8: LOAD_NAME 'x'
DEBUG:xpython.pyvm2:  frame.stack: [2]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            10: LOAD_NAME 'y'
DEBUG:xpython.pyvm2:  frame.stack: [2, 3]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            12: INPLACE_POWER
DEBUG:xpython.pyvm2:  frame.stack: [8]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            14: STORE_NAME 'x'
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            16: LOAD_CONST None
DEBUG:xpython.pyvm2:  frame.stack: [None]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            18: RETURN_VALUE

The above showed straight-line code, so you see all of the instructions. But don’t confuse this with a disassembler like pydisasm from xdis. The below example, with conditional branching example makes this more clear:

$ xpython -vvc "x = 6 if __name__ != '__main__' else 10"
DEBUG:xpython.pyvm2:make_frame: code=<code object <module> at 0x7f2dd0d2f150, file "<string x = 6 if __name__ !=>", line 1>, callargs={}, f_globals=(<class 'dict'>, 139834753714688), f_locals=(<class 'NoneType'>, 94349724270016)
DEBUG:xpython.pyvm2:<Frame at 0x7f2dd039ded0: '<string x = 6 if __name__ !=>' @ 1>
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:Line    1,   0: LOAD_NAME '__name__'
DEBUG:xpython.pyvm2:  frame.stack: ['__main__']
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             2: LOAD_CONST '__main__'
DEBUG:xpython.pyvm2:  frame.stack: ['__main__', '__main__']
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             4: COMPARE_OP 3
DEBUG:xpython.pyvm2:  frame.stack: [False]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:             6: POP_JUMP_IF_FALSE 12
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            12: LOAD_CONST 10
DEBUG:xpython.pyvm2:  frame.stack: [10]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            14: STORE_NAME 'x'
DEBUG:xpython.pyvm2:  frame.stack: []
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            16: LOAD_CONST None
DEBUG:xpython.pyvm2:  frame.stack: [None]
DEBUG:xpython.pyvm2:  blocks     : []
INFO:xpython.pyvm2:            18: RETURN_VALUE

Status:

Currently only Python 2.5 - 2.7, and 3.2 - 3.7 bytecode is supported. Until there is more interest or I get support or funding, I am not contemplating expanding to 3.8 and beyond for a while.

A shout out to xdis which has made cross version interpretation and expanding to other versions easier.

Whereas Byterun was a bit loose in accepting bytecode opcodes that is invalid for particular Python but may be valid for another; x-python is more stringent. This has pros and cons. On the plus side Byterun might run certain Python 3.4 bytecode because the opcode sets are similar. However starting with Python 3.5 and beyond the likelihood gets much less because, while the underlying opcode names may be the same, the semantics of the operation may change subtely. See for example https://github.com/nedbat/byterun/issues/34.

Internally Byterun needs the kind of overhaul we have here to be able to scale to support bytecode for more Pythons, and to be able to run bytecode across different versions of Python. Specifically, you can’t rely on Python’s dis module if you expect to expect to run a bytecode other than the bytecode that the interpreter is running.

In x-python there is a clear distinction between the version being interpreted and the version of Python that is running. There is tighter control of opcodes and an opcode’s implementation is kept for each Python version. So we’ll warn early when something is invalid. You can run 3.3 bytecode using Python 3.7 (largely).

The “largely” part is because the interpreter has always made use of Python builtins. When a Python version running the interperter matches a supported bytecode close enough, the interpreter can (and does) make use interpreter internals. For example, built-in functions like range() are supported this way.

Currently running 2.7 bytecode on 3.x is often not feasible since the runtime and internal libraries used like inspect are too different.

Over time more of Python’s internals may get added so we have better cross-version compatability, so that is a possibility. Harder is to run later byecode from earlier Python versions. The callenge here is that many new features like asynchronous I/O and concurrency primatives are not in the older versions and may not easily be simulated. However that too is a possibility if there is interest.

You can run many of the tests that Python uses to test itself, and those work. Right now this program works best on Python up to 3.4 when life in Python was much simpler. It runs over 300 in Python’s test suite for itself without problems.

Moving back and forward from 3.4 things worse. Python 3.5 is pretty good. Python 3.6 and 3.7 is okay but needs work.

History

This is a fork of Byterun. which is a pure-Python implementation of a Python bytecode execution virtual machine. Net Batchelder started it (based on work from Paul Swartz) to get a better understanding of bytecodes so he could fix branch coverage bugs in coverage.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

x-python-1.1.0.tar.gz (68.9 kB view details)

Uploaded Source

Built Distributions

x_python-1.1.0-py3.7.egg (96.9 kB view details)

Uploaded Egg

x_python-1.1.0-py3.6.egg (96.8 kB view details)

Uploaded Egg

x_python-1.1.0-py3.5.egg (98.2 kB view details)

Uploaded Egg

x_python-1.1.0-py3.4.egg (98.4 kB view details)

Uploaded Egg

x_python-1.1.0-py3.3.egg (99.9 kB view details)

Uploaded Egg

x_python-1.1.0-py3.2.egg (97.8 kB view details)

Uploaded Egg

x_python-1.1.0-py3-none-any.whl (46.3 kB view details)

Uploaded Python 3

x_python-1.1.0-py2.7.egg (96.3 kB view details)

Uploaded Egg

x_python-1.1.0-py2-none-any.whl (46.3 kB view details)

Uploaded Python 2

File details

Details for the file x-python-1.1.0.tar.gz.

File metadata

  • Download URL: x-python-1.1.0.tar.gz
  • Upload date:
  • Size: 68.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x-python-1.1.0.tar.gz
Algorithm Hash digest
SHA256 f892bc93a8da9aef3f04dc1bf861a9644fdd13da80219499b6e87008b67ff3be
MD5 51f6d15bb6240abdfa4cac961996bf50
BLAKE2b-256 1db4de6186294f1f686001b4626c967fa0d5df3579258b0402cbb1b90471d3cc

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.7.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.7.egg
  • Upload date:
  • Size: 96.9 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.7.egg
Algorithm Hash digest
SHA256 1abc4cd40ec8db8e4899fc1b08d79744bccd4c00a0a679b35f690d92cab9a265
MD5 50763549338a12908de4302cf79716c0
BLAKE2b-256 50391e37fb4e4a8b70ad89940df0cf69c28e3c6f5919df3e5db1e980c51396c6

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.6.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.6.egg
  • Upload date:
  • Size: 96.8 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.6.egg
Algorithm Hash digest
SHA256 49671a2ac4e3ed10c2cef878337dae03d0e7e02c3c9336f679499ac2cd45102c
MD5 c0142b34006f33a372651c0fc35dd6dd
BLAKE2b-256 3354d86ae446984b62b1c51723accd427cdfc940ef7487b5177ec568c4106081

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.5.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.5.egg
  • Upload date:
  • Size: 98.2 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.5.egg
Algorithm Hash digest
SHA256 b27a6a1cff95b1663219dabb6ba9fc98facea52a5f6efc589529a498d0a43547
MD5 0c53ef04718f2f7c92dc6d327b85a764
BLAKE2b-256 934277ee0aa31098de7db03e4cb695cb98282ede1c95fe72656956f647327cc2

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.4.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.4.egg
  • Upload date:
  • Size: 98.4 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.4.egg
Algorithm Hash digest
SHA256 907c73395cf02b9ec15817c65495bf38f7c64b1c27232ad0797cdf61c5c3e21d
MD5 86210b049e8e6816772fba0f8991581c
BLAKE2b-256 d20759c12aa14b0fda20844491ab007d909c43387f1b20941c96c1c83b43d2bd

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.3.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.3.egg
  • Upload date:
  • Size: 99.9 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.3.egg
Algorithm Hash digest
SHA256 1d6083312299d922794b48187f535bcabe5947438da032b7b4c3604b5ee051f6
MD5 cc5469b832123ab54b21c57a2080c35f
BLAKE2b-256 2d6dac4ea15d5ad6e513bcf49d419cb7a2c9a35487f1eb57c601c34bef0c12b9

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3.2.egg.

File metadata

  • Download URL: x_python-1.1.0-py3.2.egg
  • Upload date:
  • Size: 97.8 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3.2.egg
Algorithm Hash digest
SHA256 d53f1a371c9627df5b3963a83ef7cddc7ce0ef2cb1aa6572557717bf8d9adbdd
MD5 60237acbd94767a743b9ac63dbf8f222
BLAKE2b-256 6c09073012ac743ca94ba52d8e533d622ca6af1e67d8cee6ba9b786600d23d47

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: x_python-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 898dd342bdb487ec33540515d1b12e9e57e6d2b50938fdd1c2b5ffdae1959715
MD5 142cbf11cbf2d6e30199288a76c7f1e0
BLAKE2b-256 65ed8778ea4aa3d20c1ea6d704f1dce52db96c2ed3048aaac5ad8d548d70cc44

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py2.7.egg.

File metadata

  • Download URL: x_python-1.1.0-py2.7.egg
  • Upload date:
  • Size: 96.3 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py2.7.egg
Algorithm Hash digest
SHA256 7f43ac7d970d4477e87449307b16a8a82ebd39f4c44efa7d05f676a277234bac
MD5 38fb3744f44d327413cfd3a5bbf58ac5
BLAKE2b-256 f2beb6dc3781120d87c8c0c22fcc756e17a18d69b295a033914ffd90f4d25e61

See more details on using hashes here.

File details

Details for the file x_python-1.1.0-py2-none-any.whl.

File metadata

  • Download URL: x_python-1.1.0-py2-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 2
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.7

File hashes

Hashes for x_python-1.1.0-py2-none-any.whl
Algorithm Hash digest
SHA256 24c7f0f47d2ab4807ef2b6ec97319c576c4411100a58a8b8189f2cf8817053f3
MD5 931ccd95bfaf24cb95030048f25ef14d
BLAKE2b-256 3ac1577d64da91ca2e41d142ce5e2572f9d0ea898dc446da85473754ee55278d

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page