How do I decompile Python 3.5 .pyc?
Asked Answered
C

3

6

I have been searching around and haven't been able to find anything that can help me to decompile Python 3.5. Does anyone know of one?

Contemptuous answered 1/3, 2016 at 23:26 Comment(4)
Hi, welcome to SO. I'm afraid this question is considered off-topic here. From the site rules: "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.". Sorry, but in light of this I think this question will be closed.Antonia
@FabioTurati I see a pretty obvious description of a problem as long as one understands the word “decompile”. This is not a question of recommending a specific tool but rather solve the problem ideally in the most standard way possible.Flow
@PavelŠimerda Well, the answers, for one, are only recommending tools. Anyway, all of this is 2 years old, and there are several upvotes. I still think my original comment is valid, but I'm not going to take any actions.Antonia
@FabioTurati Recommending a choice of tools is in my opinion part of a valid answer to a „how to achieve“ question. The criticized type of question is in my opinion along the lines of... “I know how to do stuff but please tell me which of those known tools is better.” Because that would require opinionated answers. This question does not.Flow
C
14

The ones I know about that handle Python 3.5 (and other Python versions) are:

  1. uncompyle6
  2. pycdc

[Disclamer: I develop 1]

uncompyle6 (written in Python) handles opcodes introduced in Python 3.5, while pycdc (written in C++) is still a little lacking here. But these opcodes appear only when new Python 3.5 language features are used. So the likelihood of running into this in pycdc may be small if the underlying program works on earlier versions of Python.

The situation though is a little bit different for Python 3.6 and later. Python 3.6 adds some function-call opcodes and changes the semantics of other opcodes. So in contrast to 3.5, the new opcodes appear even with code that doesn't use any of the new features used in Python 3.5, or 3.6. Python 3.7, yet again, adds method opcodes and changes the semantics of of others; and right now pycdc doesn't support that. 3.8 changes code generation a bit more than others with it's removal of SETUP_LOOP.

uncompyle6 is addressing some of these these, with the prodding of various bug reports. And with the introduction of 3.6, more of the newer 3.5 opcodes and features appear more often.

uncompyle6 is weak for 3.7 in handling control flow and even weaker for 3.8, even though it is probably the current front runner. Therefore, what I have done here is to create a new project altogether just to handle Python control flow. Just this alone is hard because of Python's rich control structures. In addition to exception handling which needs special handling to and edges in a control-flow graph, there are else blocks that can appear as part of for, while, and try structures; also, there are finally blocks.

When that project can handle things reasonably well (and right now it can't), I will put that first into forked code in project https://github.com/rocky/python-decompile3. This is hard stuff; volunteers are welcome here.

Although neither uncompyle6 nor pycdc are seriously keeping up with changes to Python, for now, uncompyle6 does a more thorough job. You can look at the issue trackers for each of the problems to get an up-to-date sense of where things stand.

Recent history with uncompyle6 and decompyle3 is that things are to the point where fixing some problems may break others. Let me explain. uncompyle6 and decompyle3 pattern match on instructions. There may be an particular pattern that fails 50% of the time. Over time I'll refine the pattern to something more complicated that fails less, say 25% of the time, but specific instances worked with the 50% pattern used previously.

More recently we have added additional checks in decompyle3 and uncompyle6 to do additional flow-control checks at grammar reduction time. However this again suggests a better rethinking is needed using control-flow dominator information. This may be done on a fork off of decompyle3.

Given this, my suggestion currently is that when there is a problem with uncompyle6 is to try different versions, use pycdc, or when practical, compare results of different decompilers.

Cioffred answered 26/7, 2016 at 14:59 Comment(3)
uncompyle6 just saved my ass after a horrendous issue with my laptop garbled my .py file, but the .pyc came up clean. Everything seems decompiled correctly! (An assert statement became an if not x raise AssertionError but otherwise all good)Jewelljewelle
Am glad uncompyle6 helped. It does have rules for assert statement, but on the other hand, any decompiler has to be satisfied with it producing equivalent code which I guess is the case here. If that is not the case, then feel free to open an issue after reading how to report a bug. And while you are on github, consider upvoting the project. Although right now that is the highest rating (aside from realgud in the realgud group), I do use the ratings to help me decide on which project to work on when there is a choice. And I note that right now uncompyle6 is ranked behind pycdc which I admire.Cioffred
I'm not sure this classifies as a bug, and there may be no way to tell from the pyc if the assert statement was used. Upvoted on github.Jewelljewelle
P
4

To decompile compiled .pyc python3 files, I used uncompyle6 in my current Ubuntu OS as follows:

(i)Installation of uncompyle6: pip3 install uncompyle6

(ii)To create a .py file from .pyc file Run: uncompyle6 -o . your_filename.pyc

(iii)Automatically a new .py file will be created with the same existing .pyc file name.

Hope this will help.

Paulita answered 27/10, 2017 at 5:26 Comment(0)
P
1

for now is 2020-01-06, the latest uncompyle6 support Python 3.8.0 well -> should also support your Python 3.5 well.

  • Example:

    • uncompyle6 ../pyc/utils.cpython-38.pyc > ../pyc/utils.py
  • Output:

    • origin py vs decompiled py:

Pulchi answered 6/1, 2020 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.