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

  • Experiment with additional opcodes, or ways to change the run-time environment

  • 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 run 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.

I may also experiment with faster ways to support trace callbacks such as those used in a debugger. In particular I may add a BREAKPOINT instruction to support fast breakpoints and breakpointing on a particular instruction that doesn’t happen to be on a line boundary.

Although this is far in the future, suppose you to add a race detector? It might be easier to prototype it in Python here. (This assumes the interpreter supports threading well, I suspect it doesn’t)

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.vm:L. 1   @  0: LOAD_CONST (2, 3)
INFO:xpython.vm:       @  2: UNPACK_SEQUENCE 2
INFO:xpython.vm:       @  4: STORE_NAME x
INFO:xpython.vm:       @  6: STORE_NAME y
INFO:xpython.vm:L. 1   @  8: LOAD_NAME x
INFO:xpython.vm:       @ 10: LOAD_NAME y
INFO:xpython.vm:       @ 12: INPLACE_POWER
INFO:xpython.vm:       @ 14: STORE_NAME x
INFO:xpython.vm:       @ 16: LOAD_CONST None
INFO:xpython.vm:       @ 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.vm:make_frame: code=<code object <module> at 0x7f7acd353420, file "<string x, y = 2, 3; x **= y>", line 1>, callargs={}, f_globals=(<class 'dict'>, 140165406216272), f_locals=(<class 'NoneType'>, 94599533407680)
DEBUG:xpython.vm:<Frame at 0x7f7acd322650: '<string x, y = 2, 3; x **= y>':1 @-1>
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:L. 1   @  0: LOAD_CONST (2, 3) <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [(2, 3)]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  2: UNPACK_SEQUENCE 2 <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [3, 2]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  4: STORE_NAME x <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [3]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  6: STORE_NAME y <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:L. 1   @  8: LOAD_NAME x <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [2]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 10: LOAD_NAME y <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [2, 3]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 12: INPLACE_POWER  <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [8]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 14: STORE_NAME x <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 16: LOAD_CONST None <module> in <string x, y = 2, 3; x **= y>:1
DEBUG:xpython.vm:  frame.stack: [None]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 18: RETURN_VALUE  <module> in <string x, y = 2, 3; x **= y>:1

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.vm:make_frame: code=<code object <module> at 0x7fd8061cd270, file "<string x = 6 if __name__ !=>", line 1>, callargs={}, f_globals=(<class 'dict'>, 140565793497328), f_locals=(<class 'NoneType'>, 94471841324480)
DEBUG:xpython.vm:<Frame at 0x7fd8061d1490: '<string x = 6 if __name__ !=>':1 @-1>
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:L. 1   @  0: LOAD_NAME __name__ <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: ['__main__']
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  2: LOAD_CONST __main__ <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: ['__main__', '__main__']
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  4: COMPARE_OP 3 <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: [False]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @  6: POP_JUMP_IF_FALSE 12 <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 12: LOAD_CONST 10 <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: [10]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 14: STORE_NAME x <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: []
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 16: LOAD_CONST None <module> in <string x = 6 if __name__ !=>:1
DEBUG:xpython.vm:  frame.stack: [None]
DEBUG:xpython.vm:  blocks     : []
INFO:xpython.vm:       @ 18: RETURN_VALUE  <module> in <string x = 6 if __name__ !=>:1

Status:

Currently bytecode from Python versions 3.7 - 3.2, and 2.7 - 2.5 are supported. We also support PyPy bytecode. Until there is more interest or I get help or funding, extending to 3.8 and beyond is on hold.

xdis eases the difficulty of cross-version interpretation, expanding to handle multiple Python versions, and printing instructions.

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.2.0.tar.gz (109.4 kB view details)

Uploaded Source

Built Distributions

x_python-1.2.0-py3.7.egg (111.1 kB view details)

Uploaded Egg

x_python-1.2.0-py3.6.egg (111.0 kB view details)

Uploaded Egg

x_python-1.2.0-py3.5.egg (112.5 kB view details)

Uploaded Egg

x_python-1.2.0-py3.4.egg (112.8 kB view details)

Uploaded Egg

x_python-1.2.0-py3.3.egg (114.3 kB view details)

Uploaded Egg

x_python-1.2.0-py3.2.egg (112.1 kB view details)

Uploaded Egg

x_python-1.2.0-py3-none-any.whl (53.9 kB view details)

Uploaded Python 3

x_python-1.2.0-py2.7.egg (110.5 kB view details)

Uploaded Egg

x_python-1.2.0-py2-none-any.whl (53.9 kB view details)

Uploaded Python 2

File details

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

File metadata

  • Download URL: x-python-1.2.0.tar.gz
  • Upload date:
  • Size: 109.4 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.2.0.tar.gz
Algorithm Hash digest
SHA256 6cb754891a6948575e3dd4c98777cc86173705838efb546e8d8df51d1e52d912
MD5 a78a45c984d1a477267bc32a9d36f573
BLAKE2b-256 a28cf5a6b214141002be87941570af0195a38f0aebb018eae9282355fe0eb60e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.7.egg
  • Upload date:
  • Size: 111.1 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.2.0-py3.7.egg
Algorithm Hash digest
SHA256 0000beccebe0ea969faac56c817f6b21ccca0d29335741f5ef3a55bf2dfa038d
MD5 e6d968b7b1b18928a1f4b40ed539191e
BLAKE2b-256 1eeca9aa75e7aa17ffd003f275438dfc5b299447d4d03af93e150aa33bbff5fa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.6.egg
  • Upload date:
  • Size: 111.0 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.2.0-py3.6.egg
Algorithm Hash digest
SHA256 70ce35baaec92e9f9f63a5fe158c91209ac5e05e27674abebca870b9692e4139
MD5 7a4120a85f5d9a7ea4a46cd199787cb6
BLAKE2b-256 7bb92dd1b4c58a23d85ab870dff86653599598bbf36a3d32406e0825040cf05c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.5.egg
  • Upload date:
  • Size: 112.5 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.2.0-py3.5.egg
Algorithm Hash digest
SHA256 5a2a5e6ee861f21d9de79d65ef436336c78b8d407ba75850a2060453a7690b05
MD5 0de0ca819b7b866c0154bb5a67676e2f
BLAKE2b-256 ded9e28d1b99019be00f3187fc6af5c0c6b654265735ca798ffd9169fc3cfc24

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.4.egg
  • Upload date:
  • Size: 112.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.2.0-py3.4.egg
Algorithm Hash digest
SHA256 b092b797ea1855f73cc68959194dd2b6d2922baddd94c2b4291c3b83622347fd
MD5 7a6af0824cc83839777f63f7e7d4193b
BLAKE2b-256 627231b675695549e4fa353828aea4b7fd80e43e356ca3cab21b8d772bdaa890

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.3.egg
  • Upload date:
  • Size: 114.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.2.0-py3.3.egg
Algorithm Hash digest
SHA256 7c104ba8fb01296a91a62f9d6ac86c3c52613faf2167407091ebe18a66d5b013
MD5 33f9b4026ef17a217b555620db109bc4
BLAKE2b-256 e15e421dbb08b068e235c29b7c71c00b1f0afbdc871378aa0d81d64db5b63ae2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3.2.egg
  • Upload date:
  • Size: 112.1 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.2.0-py3.2.egg
Algorithm Hash digest
SHA256 80d81ee46746aa7c573dde70b8438f3e951a134f46646518eba1fc9d27c43e53
MD5 05d434a7b9b587a3e07cf812119bbab6
BLAKE2b-256 c1521d4abd46d50a001e536b1b55ff0f85109bd68c44a2c93af07734137206ed

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 53.9 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e776fd79818b67e490b9b005b4ff526b5efc73f327c280ed28f778afc4c1a144
MD5 3248242483ab3fd2a0f71c8cf54f59cb
BLAKE2b-256 917f9a88ff0a9d5f2224c55d47727bf1b1c1a74987cda8493d2003342eda72f2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py2.7.egg
  • Upload date:
  • Size: 110.5 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.2.0-py2.7.egg
Algorithm Hash digest
SHA256 27ca142d35739d99393a72f8b17c89222fa4a6665688a4cd369fa9e88e8ce0d9
MD5 765b5525b710379b9c64e1aed9524c47
BLAKE2b-256 1aba62fa94bbab203604e779a8e6f4eb5f3f9455eb062047cca7d53a20f998db

See more details on using hashes here.

File details

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

File metadata

  • Download URL: x_python-1.2.0-py2-none-any.whl
  • Upload date:
  • Size: 53.9 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.2.0-py2-none-any.whl
Algorithm Hash digest
SHA256 cd43070393733751c196b5e544f6bc801bbd7d369c3f377c0623e013e936d3ad
MD5 eb550d171722dd59f9b551b20a9671ef
BLAKE2b-256 e84f41b155582bba09734322355e3c9cf7ea42c938129a049e74dd4c51a833d1

See more details on using hashes here.

Supported by

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