Python 对代码对象使用uncompyle6的正确方法是什么?

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,

我在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, 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[]”也不见了。我想这是因为其他地方的代码设置了这个部分

总之,事情有点古怪,因为顶级上下文不正确。对于一个完整的程序,应该使用一个语法规则(假设这是一个表达式),而不是一个语法规则