- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 .pyc
文件。我需要了解该文件的内容才能知道 python 的反汇编程序是如何工作的,即如何从 .pyc
文件生成类似 dis.dis(function)
的输出内容。
例如
>>> def sqr(x):
... return x*x
...
>>> import dis
>>> dis.dis(sqr)
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
7 RETURN_VALUE
我需要使用 .pyc
文件获得这样的输出。
最佳答案
.pyc
文件包含一些元数据和一个 marshal
ed 代码
对象;加载 code
对象并反汇编使用:
import dis, marshal, sys
header_sizes = [
# (size, first version this applies to)
# pyc files were introduced in 0.9.2 way, way back in June 1991.
(8, (0, 9, 2)), # 2 bytes magic number, \r\n, 4 bytes UNIX timestamp
(12, (3, 6)), # added 4 bytes file size
# bytes 4-8 are flags, meaning of 9-16 depends on what flags are set
# bit 0 not set: 9-12 timestamp, 13-16 file size
# bit 0 set: 9-16 file hash (SipHash-2-4, k0 = 4 bytes of the file, k1 = 0)
(16, (3, 7)), # inserted 4 bytes bit flag field at 4-8
# future version may add more bytes still, at which point we can extend
# this table. It is correct for Python versions up to 3.9
]
header_size = next(s for s, v in reversed(header_sizes) if sys.version_info >= v)
with open(pycfile, "rb") as f:
metadata = f.read(header_size) # first header_size bytes are metadata
code = marshal.load(f) # rest is a marshalled code object
dis.dis(code)
bisect
模块演示:
>>> import bisect
>>> import dis, marshal
>>> import sys
>>> header_sizes = [(8, (0, 9, 2)), (12, (3, 6)), (16, (3, 7))]
>>> header_size = next(s for s, v in reversed(header_sizes) if sys.version_info >= v)
>>> pycfile = getattr(bisect, '__cached__', pycfile.__file__)
>>> with open(pycfile, "rb") as f:
... metadata = f.read(header_size) # first header_size bytes are metadata
... code = marshal.load(f) # rest is bytecode
...
>>> dis.dis(code)
1 0 LOAD_CONST 0 ('Bisection algorithms.')
2 STORE_NAME 0 (__doc__)
3 4 LOAD_CONST 12 ((0, None))
6 LOAD_CONST 3 (<code object insort_right at 0x10694f3a0, file "/.../lib/python3.8/bisect.py", line 3>)
8 LOAD_CONST 4 ('insort_right')
10 MAKE_FUNCTION 1 (defaults)
12 STORE_NAME 1 (insort_right)
15 14 LOAD_CONST 13 ((0, None))
16 LOAD_CONST 5 (<code object bisect_right at 0x10694f2f0, file "/.../lib/python3.8/bisect.py", line 15>)
18 LOAD_CONST 6 ('bisect_right')
20 MAKE_FUNCTION 1 (defaults)
22 STORE_NAME 2 (bisect_right)
36 24 LOAD_CONST 14 ((0, None))
26 LOAD_CONST 7 (<code object insort_left at 0x10694f240, file "/.../lib/python3.8/bisect.py", line 36>)
28 LOAD_CONST 8 ('insort_left')
30 MAKE_FUNCTION 1 (defaults)
32 STORE_NAME 3 (insort_left)
49 34 LOAD_CONST 15 ((0, None))
36 LOAD_CONST 9 (<code object bisect_left at 0x10694f190, file "/.../lib/python3.8/bisect.py", line 49>)
38 LOAD_CONST 10 ('bisect_left')
40 MAKE_FUNCTION 1 (defaults)
42 STORE_NAME 4 (bisect_left)
71 44 SETUP_FINALLY 12 (to 58)
72 46 LOAD_CONST 1 (0)
48 LOAD_CONST 11 (('*',))
50 IMPORT_NAME 5 (_bisect)
52 IMPORT_STAR
54 POP_BLOCK
56 JUMP_FORWARD 20 (to 78)
73 >> 58 DUP_TOP
60 LOAD_NAME 6 (ImportError)
62 COMPARE_OP 10 (exception match)
64 POP_JUMP_IF_FALSE 76
66 POP_TOP
68 POP_TOP
70 POP_TOP
74 72 POP_EXCEPT
74 JUMP_FORWARD 2 (to 78)
>> 76 END_FINALLY
77 >> 78 LOAD_NAME 2 (bisect_right)
80 STORE_NAME 7 (bisect)
78 82 LOAD_NAME 1 (insort_right)
84 STORE_NAME 8 (insort)
86 LOAD_CONST 2 (None)
88 RETURN_VALUE
Disassembly of <code object insort_right at 0x10694f3a0, file "/.../lib/python3.8/bisect.py", line 3>:
12 0 LOAD_GLOBAL 0 (bisect_right)
2 LOAD_FAST 0 (a)
4 LOAD_FAST 1 (x)
6 LOAD_FAST 2 (lo)
8 LOAD_FAST 3 (hi)
10 CALL_FUNCTION 4
12 STORE_FAST 2 (lo)
13 14 LOAD_FAST 0 (a)
16 LOAD_METHOD 1 (insert)
18 LOAD_FAST 2 (lo)
20 LOAD_FAST 1 (x)
22 CALL_METHOD 2
24 POP_TOP
26 LOAD_CONST 1 (None)
28 RETURN_VALUE
Disassembly of <code object bisect_right at 0x10694f2f0, file "/.../lib/python3.8/bisect.py", line 15>:
26 0 LOAD_FAST 2 (lo)
2 LOAD_CONST 1 (0)
4 COMPARE_OP 0 (<)
6 POP_JUMP_IF_FALSE 16
27 8 LOAD_GLOBAL 0 (ValueError)
10 LOAD_CONST 2 ('lo must be non-negative')
12 CALL_FUNCTION 1
14 RAISE_VARARGS 1
28 >> 16 LOAD_FAST 3 (hi)
18 LOAD_CONST 3 (None)
20 COMPARE_OP 8 (is)
22 POP_JUMP_IF_FALSE 32
29 24 LOAD_GLOBAL 1 (len)
26 LOAD_FAST 0 (a)
28 CALL_FUNCTION 1
30 STORE_FAST 3 (hi)
30 >> 32 LOAD_FAST 2 (lo)
34 LOAD_FAST 3 (hi)
36 COMPARE_OP 0 (<)
38 POP_JUMP_IF_FALSE 80
31 40 LOAD_FAST 2 (lo)
42 LOAD_FAST 3 (hi)
44 BINARY_ADD
46 LOAD_CONST 4 (2)
48 BINARY_FLOOR_DIVIDE
50 STORE_FAST 4 (mid)
32 52 LOAD_FAST 1 (x)
54 LOAD_FAST 0 (a)
56 LOAD_FAST 4 (mid)
58 BINARY_SUBSCR
60 COMPARE_OP 0 (<)
62 POP_JUMP_IF_FALSE 70
64 LOAD_FAST 4 (mid)
66 STORE_FAST 3 (hi)
68 JUMP_ABSOLUTE 32
33 >> 70 LOAD_FAST 4 (mid)
72 LOAD_CONST 5 (1)
74 BINARY_ADD
76 STORE_FAST 2 (lo)
78 JUMP_ABSOLUTE 32
34 >> 80 LOAD_FAST 2 (lo)
82 RETURN_VALUE
Disassembly of <code object insort_left at 0x10694f240, file "/.../lib/python3.8/bisect.py", line 36>:
45 0 LOAD_GLOBAL 0 (bisect_left)
2 LOAD_FAST 0 (a)
4 LOAD_FAST 1 (x)
6 LOAD_FAST 2 (lo)
8 LOAD_FAST 3 (hi)
10 CALL_FUNCTION 4
12 STORE_FAST 2 (lo)
46 14 LOAD_FAST 0 (a)
16 LOAD_METHOD 1 (insert)
18 LOAD_FAST 2 (lo)
20 LOAD_FAST 1 (x)
22 CALL_METHOD 2
24 POP_TOP
26 LOAD_CONST 1 (None)
28 RETURN_VALUE
Disassembly of <code object bisect_left at 0x10694f190, file "/.../lib/python3.8/bisect.py", line 49>:
60 0 LOAD_FAST 2 (lo)
2 LOAD_CONST 1 (0)
4 COMPARE_OP 0 (<)
6 POP_JUMP_IF_FALSE 16
61 8 LOAD_GLOBAL 0 (ValueError)
10 LOAD_CONST 2 ('lo must be non-negative')
12 CALL_FUNCTION 1
14 RAISE_VARARGS 1
62 >> 16 LOAD_FAST 3 (hi)
18 LOAD_CONST 3 (None)
20 COMPARE_OP 8 (is)
22 POP_JUMP_IF_FALSE 32
63 24 LOAD_GLOBAL 1 (len)
26 LOAD_FAST 0 (a)
28 CALL_FUNCTION 1
30 STORE_FAST 3 (hi)
64 >> 32 LOAD_FAST 2 (lo)
34 LOAD_FAST 3 (hi)
36 COMPARE_OP 0 (<)
38 POP_JUMP_IF_FALSE 80
65 40 LOAD_FAST 2 (lo)
42 LOAD_FAST 3 (hi)
44 BINARY_ADD
46 LOAD_CONST 4 (2)
48 BINARY_FLOOR_DIVIDE
50 STORE_FAST 4 (mid)
66 52 LOAD_FAST 0 (a)
54 LOAD_FAST 4 (mid)
56 BINARY_SUBSCR
58 LOAD_FAST 1 (x)
60 COMPARE_OP 0 (<)
62 POP_JUMP_IF_FALSE 74
64 LOAD_FAST 4 (mid)
66 LOAD_CONST 5 (1)
68 BINARY_ADD
70 STORE_FAST 2 (lo)
72 JUMP_ABSOLUTE 32
67 >> 74 LOAD_FAST 4 (mid)
76 STORE_FAST 3 (hi)
78 JUMP_ABSOLUTE 32
68 >> 80 LOAD_FAST 2 (lo)
82 RETURN_VALUE(
请注意,这是将顶级代码对象、定义模块以及函数和类的代码对象分开。在 Python 3.6 及更早版本中,dis.dis()
函数不会递归。在这些版本中,如果您想分析其中包含的函数,则需要从顶级 code.co_consts
数组加载嵌套的 code
对象。例如,insort_right
函数的代码对象加载了 LOAD_CONST 3
,因此您在该索引处查找代码对象:
>>> code.co_consts[3]
<code object insort_right at 0x10694f3a0, file "/.../lib/python3.8/bisect.py", line 3>
>>> dis.dis(code.co_consts[3])
12 0 LOAD_GLOBAL 0 (bisect_right)
2 LOAD_FAST 0 (a)
4 LOAD_FAST 1 (x)
6 LOAD_FAST 2 (lo)
8 LOAD_FAST 3 (hi)
10 CALL_FUNCTION 4
12 STORE_FAST 2 (lo)
13 14 LOAD_FAST 0 (a)
16 LOAD_METHOD 1 (insert)
18 LOAD_FAST 2 (lo)
20 LOAD_FAST 1 (x)
22 CALL_METHOD 2
24 POP_TOP
26 LOAD_CONST 1 (None)
28 RETURN_VALUE
我个人会避免尝试使用匹配的 Python 版本和 marshal
模块以外的任何东西来解析 .pyc
文件。 marshal
格式基本上是一种内部序列化格式,随着 Python 本身的需要而变化。列表理解和 with
语句和 async
/await
等新功能需要对格式进行新添加,除 C source code 外未发布。 .
如果你真的走这条路,并设法到达read a code
object通过使用模块以外的其他方式,您必须从代码对象的各种属性中解析出反汇编;查看dis
module source有关如何执行此操作的详细信息(例如,您必须使用 co_firSTLineno
和 co_lnotab
属性来创建 bytecode-offset-to-linenumber 映射)。
关于python - 我如何理解 .pyc 文件内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32562163/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!