我在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
。
这似乎很不正确。我错过了什么还是仅仅是一个错误?
答案 0 :(得分:1)
这不是一个完整的答案,但它应该使您对正在发生的事情有所了解。
首先要注意的是,传递到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”。
摘自built-in function compile()
的Python文档:
mode参数指定必须编译的代码类型;它可以 如果source由语句序列组成,则为'exec';如果它由语句序列组成,则为'eval' 由一个表达式组成,如果由一个表达式组成,则为“单个” 单一互动声明
这里的上下文是s生成器,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...
因此,您看到.0
确实来自代码:它是在生成器内部使用的临时变量。但是,应该有某种“ for”,并且“ []”中也缺少。这是丢失的,因为我认为其他地方的代码可以起到作用。
总而言之,事情有点怪异,因为顶级上下文不正确。应该使用假定这是单个表达式的语法规则,而不是完整程序的语法规则。