C++ python bytecode disassembler and decompiler
  • C++ 84.5%
  • Python 14.9%
  • CMake 0.5%
Find a file
polfg 9c5ea2f2bc Reconstruct 3.11 while-loops (bottom-test optimization)
Python 3.11 compiles 'while cond:' with a bottom test: an entry guard
(eval cond; POP_JUMP_FORWARD_IF_FALSE end) before the body, and a
back-edge (eval cond; POP_JUMP_BACKWARD_IF_TRUE loop_start) at the end.
pycdc rendered both halves as separate 'if' blocks, so EVERY while loop
came out as 'if cond: ... if not cond: pass' and never looped.

- New ScanWhileLoops pre-pass pairs each conditional backward jump with
  the forward guard immediately preceding its target (guard skipping to
  the instruction after the back-edge) to identify genuine while loops.
- At the guard, open a BLK_WHILE with the condition instead of an if.
- At the back-edge, discard the duplicated condition and close the loop,
  but only when a BLK_WHILE is actually open (guard against a
  misidentified back-edge collapsing the block stack and crashing).

Fixes while loops across all files (including nested loops and
continue). decompilation target: 237/239 files, corpus 41/95 (+1: signature; 0 regressions).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:27:24 +02:00
.github/workflows Update to upload-artifact/v4 to fix CI 2025-06-30 19:21:38 -07:00
bytes Remove additional specialized opcode that wasn't ordered with the others 2024-08-12 11:39:36 -07:00
CMakeFiles Reconstruct 3.11 while-loops (bottom-test optimization) 2026-06-08 12:27:24 +02:00
scripts Add basic bytecode and disassembly support for Python 3.12 2023-11-09 12:17:03 -08:00
tests Support Python 3.11 exception table try/except flow 2026-04-06 09:30:16 +09:00
.gitignore Support END_FOR opcode 2025-07-01 09:22:56 +05:30
ASTNode.cpp Return back a fix for Centos6/7 compilation issues not related to shadow ones 2024-03-12 22:58:43 +02:00
ASTNode.h Reconstruct 'except ... as e' for Python 3.11 + dict/set comprehension inlining 2026-06-05 12:00:11 +02:00
ASTree.cpp Reconstruct 3.11 while-loops (bottom-test optimization) 2026-06-08 12:27:24 +02:00
ASTree.h Use C++ streams over C style IO 2023-06-02 01:12:59 +02:00
bytecode.cpp Address comments 2025-08-30 20:01:32 +05:30
bytecode.h Parse exception table 2025-07-15 22:47:02 +05:30
bytecode_ops.inl Remove additional specialized opcode that wasn't ordered with the others 2024-08-12 11:39:36 -07:00
cmake_install.cmake Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
CMakeCache.txt Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
CMakeLists.txt Test runner refactor (#508) 2024-08-08 15:55:35 -07:00
data.cpp Also check EOF in getBuffer() 2025-08-28 15:58:28 -07:00
data.h Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
FastStack.h Fix SWAP_A as a real stack swap (chained comparisons, starred unpack) 2026-06-05 11:43:44 +02:00
libpycxx.a Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
LICENSE Added GPL v3 license file 2009-07-25 00:43:46 +00:00
Makefile Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
pyc_code.cpp Address comments 2025-08-30 20:01:32 +05:30
pyc_code.h Address comments 2025-08-30 20:01:32 +05:30
pyc_module.cpp Python 3.13 initial support (#497) 2024-08-07 15:39:40 -07:00
pyc_module.h Python 3.13 initial support (#497) 2024-08-07 15:39:40 -07:00
pyc_numeric.cpp Fix Long Numeric Integer representation for Python 3 2024-06-22 23:19:18 +02:00
pyc_numeric.h Fix Long Numeric Integer representation for Python 3 2024-06-22 23:19:18 +02:00
pyc_object.cpp Don't create special objects for NULL, just use NULL directly. 2017-07-05 16:36:04 -07:00
pyc_object.h Remove unnecessary template parameter in destructor. Fixes #487 2024-05-30 14:56:07 -07:00
pyc_sequence.cpp Simplify PycDict key/value storage a bit 2023-11-09 15:05:55 -08:00
pyc_sequence.h Restore changes for shadow warnings... 2024-03-12 22:55:56 +02:00
pyc_string.cpp Restore changes for shadow warnings... 2024-03-12 22:55:56 +02:00
pyc_string.h Restore changes for shadow warnings... 2024-03-12 22:55:56 +02:00
pycdas Fix std::bad_cast crash on return-in-if followed by comprehension 2026-06-08 11:49:55 +02:00
pycdas.cpp Merge pull request #564 from whoami730/exceptions 2025-08-30 10:02:14 -07:00
pycdc Reconstruct 3.11 while-loops (bottom-test optimization) 2026-06-08 12:27:24 +02:00
pycdc.cpp Clean up file handling in main()s, and remove a leak 2023-06-05 13:54:26 -07:00
README.markdown Run tests in parallel or only some with a filter 2024-06-19 17:56:06 +02:00

Decompyle++

A Python Byte-code Disassembler/Decompiler

Decompyle++ aims to translate compiled Python byte-code back into valid and human-readable Python source code. While other projects have achieved this with varied success, Decompyle++ is unique in that it seeks to support byte-code from any version of Python.

Decompyle++ includes both a byte-code disassembler (pycdas) and a decompiler (pycdc).

As the name implies, Decompyle++ is written in C++. If you wish to contribute, please fork us on github at https://github.com/zrax/pycdc

Building Decompyle++

  • Generate a project or makefile with CMake (See CMake's documentation for details)

    • The following options can be passed to CMake to control debug features:
      Option Description
      -DCMAKE_BUILD_TYPE=Debug Produce debugging symbols
      -DENABLE_BLOCK_DEBUG=ON Enable block debugging output
      -DENABLE_STACK_DEBUG=ON Enable stack debugging output
  • Build the generated project or makefile

    • For projects (e.g. MSVC), open the generated project file and build it
    • For makefiles, just run make
    • To run tests (on *nix or MSYS), run make check JOBS=4 (optional FILTER=xxxx to run only certain tests)

Usage

To run pycdas, the PYC Disassembler: ./pycdas [PATH TO PYC FILE] The byte-code disassembly is printed to stdout.

To run pycdc, the PYC Decompiler: ./pycdc [PATH TO PYC FILE] The decompiled Python source is printed to stdout. Any errors are printed to stderr.

Marshalled code objects: Both tools support Python marshalled code objects, as output from marshal.dumps(compile(...)).

To use this feature, specify -c -v <version> on the command line - the version must be specified as the objects themselves do not contain version metadata.

Authors, Licence, Credits

Decompyle++ is the work of Michael Hansen and Darryl Pogue.

Additional contributions from:

  • charlietang98
  • Kunal Parmar
  • Olivier Iffrig
  • Zlodiy

It is released under the terms of the GNU General Public License, version 3; See LICENSE file for details.