Python 对代码对象使用uncompyle6的正确方法是什么?
我在github上发现了这个例子,但它似乎已经过时了,所以我对它做了一些修改Python 对代码对象使用uncompyle6的正确方法是什么?,python,Python,我在github上发现了这个例子,但它似乎已经过时了,所以我对它做了一些修改 from uncompyle6.main import decompile import sys def uncompyle_test(): gen = (expr1 if cond1 else expr2 for A in [] if (expr3 if cond2 else expr4)) co = gen.gi_code decompile (3.6, co, sys.stdout,
from uncompyle6.main import decompile
import sys
def uncompyle_test():
gen = (expr1 if cond1 else expr2 for A in [] if (expr3 if cond2 else expr4))
co = gen.gi_code
decompile (3.6, co, sys.stdout, showast=False)
uncompyle_test()
通过运行这个,我得到了
.0A如果expr3如果cond2否则expr4
。
这似乎很不正确。我是遗漏了什么还是只是一个bug?这不是一个完整的答案,但它应该能让你对发生的事情有一些了解 首先需要注意的是,传递到
decompile()
函数的字节码版本应该与您正在运行的Python版本相同,因为这是生成的字节码类型。xdis具有确保以下各项的功能:
>>> from xdis.magics import sysinfo2float
>>> sysinfo2float()
3.6
不过,我想情况就是这样
其次,当您反编译整个程序时,会得到正确的结果:
# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.5 (default, Apr 9 2018, 01:37:56)
# [GCC 7.2.0]
# Embedded file name: exec
# Compiled at: 2018-09-18 16:10:11
# Size of source mod 2**32: 243 bytes
from uncompyle6.main import decompile
import sys
def uncompyle_test():
gen = ((expr1 if cond1 else expr2) for A in [] if (expr3 if cond2 else expr4))
co = gen.gi_code
decompile(3.6, co, sys.stdout, showast=False)
那为什么你试过的不管用呢?主要的问题是,uncompyle6需要知道它试图去挖掘什么样的东西。回想一下,compile()
函数有三种“模式”:“exec”、“eval”和“single”
从Python文档中获取:
mode参数指定必须编译的代码类型;它可以
如果源由一系列语句组成,则为“exec”,如果为“eval”,则为“eval”
由单个表达式组成,如果由
单交互语句
这里的上下文是一个生成器,eval是一种表达式。deparse()不允许您选择所指的对象,并使用“exec”。在解析的较低级别上,虽然可以区分“exec”和“single”,但目前还没有一种方法可以指定“eval”,更不用说在这个特定函数中了。我已经打开了一个uncompyle6版本来说明这一点
最后,让我们再描述一下为什么你看到了你所看到的
为此,让我们使用我编写的这个方便且独特的调试器,它向您展示了在反汇编过程中(但更重要的是在反汇编过程中)发生了什么
$ trepan3k /tmp/bug.py
(/tmp/bug.py:1): <module>
-> 1 from uncompyle6.main import decompile
Rocky's Python Trepan Python code startup loaded
(trepan3k) next 2
(/tmp/bug.py:9 @28): <module>
-- 9 uncompyle_test()
(trepan3k) step
(/tmp/bug.py:4): uncompyle_test
-> 4 def uncompyle_test():
(trepan3k) next 3
(/tmp/bug.py:7 @20): uncompyle_test
-- 7 decompile (3.6, co, sys.stdout, showast=False)
(trepan3k) disasm co
Disassembly of <code object <genexpr> at 0x7f6a3faff300, file "/tmp/bug.py", line 5>:
5 0 LOAD_FAST 0 .0
>> 2 FOR_ITER 30 to 34
4 STORE_FAST 1 A
6 LOAD_GLOBAL 0 cond2
8 POP_JUMP_IF_FALSE 14 to 14
10 LOAD_GLOBAL 1 expr3
12 JUMP_FORWARD 2 to 16
>> 14 LOAD_GLOBAL 2 expr4
>> 16 POP_JUMP_IF_FALSE 2 to 2
18 LOAD_GLOBAL 3 cond1
20 POP_JUMP_IF_FALSE 26 to 26
22 LOAD_GLOBAL 4 expr1
24 JUMP_FORWARD 2 to 28
>> 26 LOAD_GLOBAL 5 expr2
>> 28 YIELD_VALUE None
30 POP_TOP None
32 JUMP_ABSOLUTE 2 to 2
>> 34 LOAD_CONST 0 None
36 RETURN_VALUE None
(trepan3k) Leaving
trepan3k: That's all, folks...
$trepan3k/tmp/bug.py
(/tmp/bug.py:1):
->1从uncompyle6.main导入反编译
Rocky的Python Trepan Python代码启动已加载
(钻孔3K)下一个2
(/tmp/bug.py:9@28):
--9无样式测试()
(钻孔3K)台阶
(/tmp/bug.py:4):解压测试
->4 def UNCOMYLE_测试():
(钻孔3K)下一个3
(/tmp/bug.py:7@20):解压测试
--7反编译(3.6,co,sys.stdout,showast=False)
(钻孔3K)disasm公司
反汇编:
5 0加载速度0.0
>>国际热核聚变实验堆30至34的2个
4商店快1 A
6加载_全局0条件2
8如果为假,则弹出跳转14到14
10负载_全局1 expr3
12向前跳2到16
>>14负载_全局2 expr4
>>16如果为假,则弹出跳转2到2
18负载_全局3条件1
20如果为假,则弹出跳转26到26
22加载_全局4 expr1
24向前跳2到28
>>26负载_全球5 expr2
>>28收益率u值无
30首流行歌曲无首
32绝对2比2跳转
>>34负载常数0无
36返回值无
(钻孔3K)离开
trepan3k:就这些,伙计们。。。
因此您可以看到,.0
确实来自代码:它是在生成器内部使用的临时变量。然而,应该有某种形式的“for”,而且“in[]”也不见了。我想这是因为其他地方的代码设置了这个部分
总之,事情有点古怪,因为顶级上下文不正确。对于一个完整的程序,应该使用一个语法规则(假设这是一个表达式),而不是一个语法规则