Skip to main content

Python cross-version byte-code decompiler

Project description

buildstatus Pypi Installs Latest Version Supported Python Versions

packagestatus

uncompyle6

A native Python cross-version decompiler and fragment decompiler. The successor to decompyle, uncompyle, and uncompyle2.

Introduction

uncompyle6 translates Python bytecode back into equivalent Python source code. It accepts bytecodes from Python version 1.0 to version 3.8, spanning over 24 years of Python releases. We include Dropbox’s Python 2.5 bytecode and some PyPy bytecodes.

Why this?

Ok, I’ll say it: this software is amazing. It is more than your normal hacky decompiler. Using compiler technology, the program creates a parse tree of the program from the instructions; nodes at the upper levels that look a little like what might come from a Python AST. So we can really classify and understand what’s going on in sections of Python bytecode.

Building on this, another thing that makes this different from other CPython bytecode decompilers is the ability to deparse just fragments of source code and give source-code information around a given bytecode offset.

I use the tree fragments to deparse fragments of code at run time inside my trepan debuggers. For that, bytecode offsets are recorded and associated with fragments of the source code. This purpose, although compatible with the original intention, is yet a little bit different. See this for more information.

Python fragment deparsing given an instruction offset is useful in showing stack traces and can be encorporated into any program that wants to show a location in more detail than just a line number at runtime. This code can be also used when source-code information does not exist and there is just bytecode. Again, my debuggers make use of this.

There were (and still are) a number of decompyle, uncompyle, uncompyle2, uncompyle3 forks around. Many of them come basically from the same code base, and (almost?) all of them are no longer actively maintained. One was really good at decompiling Python 1.5-2.3, another really good at Python 2.7, but that only. Another handles Python 3.2 only; another patched that and handled only 3.3. You get the idea. This code pulls all of these forks together and moves forward. There is some serious refactoring and cleanup in this code base over those old forks. Even more experimental refactoring is going on in decompyle3.

This demonstrably does the best in decompiling Python across all Python versions. And even when there is another project that only provides decompilation for subset of Python versions, we generally do demonstrably better for those as well.

How can we tell? By taking Python bytecode that comes distributed with that version of Python and decompiling these. Among those that successfully decompile, we can then make sure the resulting programs are syntactically correct by running the Python interpreter for that bytecode version. Finally, in cases where the program has a test for itself, we can run the check on the decompiled code.

We are serious about testing, and use automated processes to find bugs. In the issue trackers for other decompilers, you will find a number of bugs we’ve found along the way. Very few to none of them are fixed in the other decompilers.

Requirements

The code here can be run on Python versions 2.6 or later, PyPy 3-2.4 and later. Python versions 2.4-2.7 are supported in the python-2.4 branch. The bytecode files it can read have been tested on Python bytecodes from versions 1.4, 2.1-2.7, and 3.0-3.8 and later PyPy versions.

Installation

This uses setup.py, so it follows the standard Python routine:

$ pip install -e .  # set up to run from source tree
                    # Or if you want to install instead
$ python setup.py install # may need sudo

A GNU makefile is also provided so make install (possibly as root or sudo) will do the steps above.

Running Tests

make check

A GNU makefile has been added to smooth over setting running the right command, and running tests from fastest to slowest.

If you have remake installed, you can see the list of all tasks including tests via remake --tasks

Usage

Run

$ uncompyle6 *compiled-python-file-pyc-or-pyo*

For usage help:

$ uncompyle6 -h

Verification

In older versions of Python it was possible to verify bytecode by decompiling bytecode, and then compiling using the Python interpreter for that bytecode version. Having done this the bytecode produced could be compared with the original bytecode. However as Python’s code generation got better, this no longer was feasible.

If you want Python syntax verification of the correctness of the decompilation process, add the --syntax-verify option. However since Python syntax changes, you should use this option if the bytecode is the right bytecode for the Python interpreter that will be checking the syntax.

You can also cross compare the results with either another version of uncompyle6 since there are are sometimes regressions in decompiling specific bytecode as the overall quality improves.

For Python 3.7 and above, the code in decompyle3 is generally better.

Or try specific another python decompiler like uncompyle2, unpyc37, or pycdc. Since the later two work differently, bugs here often aren’t in that, and vice versa.

There is an interesting class of these programs that is readily available give stronger verification: those programs that when run test themselves. Our test suite includes these.

And Python comes with another a set of programs like this: its test suite for the standard library. We have some code in test/stdlib to facilitate this kind of checking too.

Known Bugs/Restrictions

The biggest known and possibly fixable (but hard) problem has to do with handling control flow. (Python has probably the most diverse and screwy set of compound statements I’ve ever seen; there are “else” clauses on loops and try blocks that I suspect many programmers don’t know about.)

All of the Python decompilers that I have looked at have problems decompiling Python’s control flow. In some cases we can detect an erroneous decompilation and report that.

Python support is strongest in Python 2 for 2.7 and drops off as you get further away from that. Support is also probably pretty good for python 2.3-2.4 since a lot of the goodness of early the version of the decompiler from that era has been preserved (and Python compilation in that era was minimal)

There is some work to do on the lower end Python versions which is more difficult for us to handle since we don’t have a Python interpreter for versions 1.6, and 2.0.

In the Python 3 series, Python support is is strongest around 3.4 or 3.3 and drops off as you move further away from those versions. Python 3.0 is weird in that it in some ways resembles 2.6 more than it does 3.1 or 2.7. Python 3.6 changes things drastically by using word codes rather than byte codes. As a result, the jump offset field in a jump instruction argument has been reduced. This makes the EXTENDED_ARG instructions are now more prevalent in jump instruction; previously they had been rare. Perhaps to compensate for the additional EXTENDED_ARG instructions, additional jump optimization has been added. So in sum handling control flow by ad hoc means as is currently done is worse.

Between Python 3.5, 3.6, 3.7 there have been major changes to the MAKE_FUNCTION and CALL_FUNCTION instructions. Python

Python 3.8 removes SETUP_LOOP, SETUP_EXCEPT, BREAK_LOOP, and CONTINUE_LOOP, instructions which may make control-flow detection harder, lacking the more sophisticated control-flow analysis that is planned. We’ll see.

Currently not all Python magic numbers are supported. Specifically in some versions of Python, notably Python 3.6, the magic number has changes several times within a version.

We support only released versions, not candidate versions. Note however that the magic of a released version is usually the same as the last candidate version prior to release.

There are also customized Python interpreters, notably Dropbox, which use their own magic and encrypt bytecode. With the exception of the Dropbox’s old Python 2.5 interpreter this kind of thing is not handled.

We also don’t handle PJOrion obfuscated code. For that try: PJOrion Deobfuscator to unscramble the bytecode to get valid bytecode before trying this tool. This program can’t decompile Microsoft Windows EXE files created by Py2EXE, although we can probably decompile the code after you extract the bytecode properly. For situations like this, you might want to consider a decompilation service like Crazy Compilers. Handling pathologically long lists of expressions or statements is slow.

There is lots to do, so please dig in and help.

See Also

Release history Release notifications | RSS feed

Download files

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

Source Distribution

uncompyle6-3.7.0.tar.gz (2.4 MB view details)

Uploaded Source

Built Distributions

uncompyle6-3.7.0-py3.8.egg (610.4 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.7.egg (608.8 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.6.egg (611.7 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.5.egg (621.0 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.4.egg (624.3 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.3.egg (630.6 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3.2.egg (623.3 kB view details)

Uploaded Source

uncompyle6-3.7.0-py3-none-any.whl (312.6 kB view details)

Uploaded Python 3

uncompyle6-3.7.0-py2.7.egg (612.6 kB view details)

Uploaded Source

uncompyle6-3.7.0-py2.6.egg (613.8 kB view details)

Uploaded Source

uncompyle6-3.7.0-py2.5.egg (613.3 kB view details)

Uploaded Source

uncompyle6-3.7.0-py2.4.egg (619.3 kB view details)

Uploaded Source

uncompyle6-3.7.0-py2-none-any.whl (312.6 kB view details)

Uploaded Python 2

File details

Details for the file uncompyle6-3.7.0.tar.gz.

File metadata

  • Download URL: uncompyle6-3.7.0.tar.gz
  • Upload date:
  • Size: 2.4 MB
  • 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0.tar.gz
Algorithm Hash digest
SHA256 cb0d5dd28ed6b82da17bcb29b84f5823dc8398d9dafb0e4ee8e6f958db220134
MD5 b4fd436d288a8894232b25343ff93752
BLAKE2b-256 faa3f30e98f3728a773ddc850bec90400217301047d82aeee37aeeda97b6b43c

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.8.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.8.egg
  • Upload date:
  • Size: 610.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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.8.egg
Algorithm Hash digest
SHA256 afd5e2aeca3590b903aecb2b3a87e342b474f94996c4db2a0ffe7bb401b3b128
MD5 f62455a3b2172de5299a7ef4626e0981
BLAKE2b-256 2e8882f52f45657878b372c23d4aa364afd7b949bab73db00abc40fd02f3c344

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.7.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.7.egg
  • Upload date:
  • Size: 608.8 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.7.egg
Algorithm Hash digest
SHA256 5968488aaee6694cfaa8b9c2ea55bff648dc93701ccf8473015ffb8c87d4e5f8
MD5 00e69c5ddd0a501e4c7d6d60f821722b
BLAKE2b-256 91db9ac8541f2b7dc0a2b3687dbdde0d8edff699067ad77b402b344ed8a8e3e2

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.6.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.6.egg
  • Upload date:
  • Size: 611.7 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.6.egg
Algorithm Hash digest
SHA256 d60d8cf969cbad8bf8cb6aff64ec40f65fb9e59df9d4485cd0fec39917e6e3a6
MD5 2b63acef2d32b40155337467abfd926c
BLAKE2b-256 63470226b078bffe7348e3ad3026e6c06419e14d664901275883868c4943f052

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.5.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.5.egg
  • Upload date:
  • Size: 621.0 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.5.egg
Algorithm Hash digest
SHA256 33817fe9ea0c5835e540482844834e4476da1639a05a9f59c3a10310f2e019cc
MD5 88b7d1a65670c00577822382f4dc7b7b
BLAKE2b-256 0e1c001b5bcf42c798766cb5c35010312c6438415eacf9b0b2992342e1bf4352

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.4.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.4.egg
  • Upload date:
  • Size: 624.3 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.4.egg
Algorithm Hash digest
SHA256 8b7e80dda8d11573243f8df70378f5f115e92894dfa5851d21bca7a6bc2bbdc5
MD5 316a9fb0c22c067c58b0259705686acb
BLAKE2b-256 d3e885e8b1ea1e520d17aba30e1fe8b375917a85ba23463f956614731d79e08d

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.3.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.3.egg
  • Upload date:
  • Size: 630.6 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.3.egg
Algorithm Hash digest
SHA256 833ea7b3507d7f783bc6af3fb94968aa0190f272e9f80ba6ecfe5c68551248a8
MD5 90512a5870fd39c8b877a583a8cd13ce
BLAKE2b-256 cf14c5d548635c7e0aafe47b33afbdb5afcd1f62a4782fdbdc4676dcc552e3ed

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3.2.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py3.2.egg
  • Upload date:
  • Size: 623.3 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3.2.egg
Algorithm Hash digest
SHA256 82420c783f64b234b40fc470b527f592b560751b9cffd1bb11d4ada1fe3abb99
MD5 5ea9c7ae5aaf01324f35a6773852daf1
BLAKE2b-256 23c050ee3d8b7e75aac2629867a615c5bee1616f54716bd80df00a7ddfeb4dee

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py3-none-any.whl.

File metadata

  • Download URL: uncompyle6-3.7.0-py3-none-any.whl
  • Upload date:
  • Size: 312.6 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ece37951b1b6c044a630fcac8c4a5b7bc3c893f4bae200cd0e37a4b87986c25
MD5 7185fe694308981cb7cf3dbe63a35bdb
BLAKE2b-256 a7a4b42e0fdb48904e17ea8b1c23f14d4a6dfe2c835e3fb536e87360d88e3fa8

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py2.7.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py2.7.egg
  • Upload date:
  • Size: 612.6 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py2.7.egg
Algorithm Hash digest
SHA256 8c01aba11972341aa8156b1635d6fd5e084b1642c4c34a5d6d0829bc80b644df
MD5 f632e030cbfa5661a993e94f417c9cfb
BLAKE2b-256 4d45b93e1cd04fe3cad8f0a7da83e2f5e1218c5a40ddabdec525e38fdbbb631a

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py2.6.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py2.6.egg
  • Upload date:
  • Size: 613.8 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py2.6.egg
Algorithm Hash digest
SHA256 c2e0da3f6b01ce3d42b0570d4f839f77a44dd1738a8998910db08fc9c154da7d
MD5 87cec62b8535ced66b5c420f8645ef47
BLAKE2b-256 3cd2d686b29b2d11a7e506e4c77274b00df23eb1ae559645f1e55ede2121c4b6

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py2.5.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py2.5.egg
  • Upload date:
  • Size: 613.3 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py2.5.egg
Algorithm Hash digest
SHA256 146b24ff78cd4f57089a2343f72de006d49c2a3fd947559421eccaecfd66b0ee
MD5 8a8e58bbdd02c35ecada89e23eab1964
BLAKE2b-256 59d17b4c7cd6a8f69857b82883c2e5fdaf0820a38a10d8a1995cce194627d437

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py2.4.egg.

File metadata

  • Download URL: uncompyle6-3.7.0-py2.4.egg
  • Upload date:
  • Size: 619.3 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py2.4.egg
Algorithm Hash digest
SHA256 505f5dc977b0ac3bef41e58a12f994809a65cfd7a90f18c625f1708cc26da9b8
MD5 6c64b420b15add6e2aa221cfa330074c
BLAKE2b-256 a3f8cc54af29830e636fda4f474c5ae2b3a0ff6fde5e9e1625d088a9fef26c1b

See more details on using hashes here.

Provenance

File details

Details for the file uncompyle6-3.7.0-py2-none-any.whl.

File metadata

  • Download URL: uncompyle6-3.7.0-py2-none-any.whl
  • Upload date:
  • Size: 312.6 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.46.0 CPython/3.8.3

File hashes

Hashes for uncompyle6-3.7.0-py2-none-any.whl
Algorithm Hash digest
SHA256 b0bec130073fc5b52b41f792a28dcefea5ee9cc995e67b5cf4a6927995e48314
MD5 099baeff0e480a51ee9711377135092a
BLAKE2b-256 7df870e7347ab1d59c9abd01d35c48b3bd71443b59e242f37f5b19450d22b358

See more details on using hashes here.

Provenance

Supported by

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