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

2024-07-04 06:04:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我在github (original)上找到了这个例子,但这似乎已经过时了,所以我稍微修改了一下。在

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 if expr3 if cond2 else expr4。 这似乎很不正确。是我漏掉了什么还是只是个虫子?在


Tags: testimportgithubifsyselse例子gen
1条回答
网友
1楼 · 发布于 2024-07-04 06:04:20

这不是一个完整的答案,但它应该能让你知道发生了什么。在

首先要注意的是,传入decompile()函数的字节码版本应该与您正在运行的Python版本相同,因为这是正在生成的字节码类型。xdis具有确保:

>>> from xdis.magics import sysinfo2float
>>> sysinfo2float()
3.6

不过,我认为是这样。在

其次,当你反编译整个程序时,你会得到一个正确的结果:

^{pr2}$

为什么你的努力没有奏效?主要的问题是uncompyle6需要知道它要删除什么类型的东西。回想一下,compile()函数有三个“模式”:“exec”、“eval”和“single”。在

来自built-in function ^{}的Python文档:

The mode argument specifies what kind of code must be compiled; it can be 'exec' if source consists of a sequence of statements, 'eval' if it consists of a single expression, or 'single' if it consists of a single interactive statement

这里的上下文是s生成器,eval是一种表达式。deparse()不允许您选择您的意思,并使用“exec”。在较低级别的解析中,虽然您可以区分“exec”和“single”,但目前还没有一种方法来指定“eval”,更不用说在这个特定的函数中了。我已经打开了一个未编译的问题来注意这一点。在

最后,让我们再描述一下为什么你会看到你所看到的。在

为此,让我们使用我编写的这个方便而独特的调试器,它向您展示了在深度分解(deparing)和更重要的反汇编(disassembly)中发生了什么。在

$ 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...

因此您可以看到.0确实来自代码:它是一个临时变量,在生成器中使用。然而,应该有某种类型的“for”和“in[]”也不见了。我想,这是因为其他地方的代码设置了这个部分。在

总而言之,事情有点怪,因为顶层的上下文是不对的。假设这是一个单独的表达式的语法规则应该被使用,而不是一个完整程序的语法规则。在

相关问题 更多 >

    热门问题