Mô-đun dis trong thư viện chuẩn Python cung cấp các hàm hữu ích để phân tích bytecode Python bằng cách gỡ mã (disassemble) nó thành dạng đọc được bởi con người. Điều này giúp thực hiện các tối ưu hóa. Bytecode là chi tiết triển khai phụ thuộc vào phiên bản của trình thông dịch.
Hàm dis()
Hàm dis() tạo biểu diễn gỡ mã của bất kỳ mã nguồn Python nào: mô-đun, lớp, phương thức, hàm, hoặc đối tượng code.
>>> def hello():
... print("hello world")
>>> import dis
>>> dis.dis(hello)
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_CONST 1 ('hello world')
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUEAPI phân tích bytecode được định nghĩa trong lớp Bytecode. Constructor của nó trả về đối tượng Bytecode có các phương thức sau để phân tích bytecode:
Bytecode()
Đây là constructor. Phân tích bytecode tương ứng với một hàm, generator, phương thức, chuỗi mã nguồn, hoặc đối tượng code. Đây là trình bao bọc tiện lợi cho nhiều hàm.
>>> string = dis.Bytecode(hello) >>> for x in string: ... print(x) Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=0, starts_line=2, is_jump_target=False) Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval='hello world', argrepr="'hello world'", offset=3, starts_line=None, is_jump_target=False) Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=6, starts_line=None, is_jump_target=False) Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=9, starts_line=None, is_jump_target=False) Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=10, starts_line=None, is_jump_target=False) Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=13, starts_line=None, is_jump_target=False)
code_info()
Hàm này trả về thông tin của đối tượng code Python.
>>> dis.code_info(hello) "Name: hello\nFilename: <pyshell#2>\nArgument count: 0\nKw-only arguments: 0\nNumber of locals: 0\nStack size: 2\nFlags: OPTIMIZED, NEWLOCALS, NOFREE\nConstants:\n 0: None\n 1: 'hello world'\nNames:\n 0: print"
show_code()
Hàm này in thông tin code chi tiết của mô-đun, hàm hoặc lớp Python.
>>> dis.show_code(hello) Name: hello Filename: <pyshell#2> Argument count: 0 Kw-only arguments: 0 Number of locals: 0 Stack size: 2 Flags: OPTIMIZED, NEWLOCALS, NOFREE Constants: 0: None 1: 'hello world' Names: 0: print
disassemble()
Hàm này gỡ mã một đối tượng code và cho đầu ra chia thành các cột sau:
- số dòng, cho lệnh đầu tiên của mỗi dòng
- lệnh hiện tại, chỉ ra bằng
--> - lệnh có nhãn, chỉ ra bằng
>> - địa chỉ của lệnh
- tên mã phép toán
- tham số phép toán
- giải thích tham số trong ngoặc đơn.
>>> codeInString = 'a = 5\nb = 6\nsum = a + b \nprint("sum = ",sum)'
>>> codeObject = compile(codeInString, 'sumstring', 'exec')
>>> dis.disassemble(codeObject)Đầu ra
1 0 LOAD_CONST 0 (5)
3 STORE_NAME 0 (a)
2 6 LOAD_CONST 1 (6)
9 STORE_NAME 1 (b)
3 12 LOAD_NAME 0 (a)
15 LOAD_NAME 1 (b)
18 BINARY_ADD
19 STORE_NAME 2 (sum)
4 22 LOAD_NAME 3 (print)
25 LOAD_CONST 2 ('sum =')
28 LOAD_NAME 2 (sum)
31 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
34 POP_TOP
35 LOAD_CONST 3 (None)
38 RETURN_VALUEget_instructions()
Hàm này trả về một iterator qua các lệnh trong hàm, phương thức, chuỗi mã nguồn hoặc đối tượng code được cung cấp. Iterator tạo ra một chuỗi các named tuple Instruction đưa ra chi tiết của mỗi phép toán trong mã cung cấp.
>>> it = dis.get_instructions(code)
>>> for i in it:
... print(i)
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=, argrepr='', offset=0, starts_line=2, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval='hello', argrepr="'hello'", offset=3, starts_line=None, is_jump_target=False)
Instruction(opname='MAKE_FUNCTION', opcode=132, arg=0, argval=0, argrepr='', offset=6, starts_line=None, is_jump_target=False)
Instruction(opname='STORE_NAME', opcode=90, arg=0, argval='hello', argrepr='hello', offset=9, starts_line=None, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=None, argrepr='None', offset=12, starts_line=None, is_jump_target=False)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=15, starts_line=None, is_jump_target=False)Thông tin hàm ở dạng đối tượng giống tuple với các tham số như sau:
| Instruction | Chi tiết cho một phép toán bytecode |
|---|---|
| opcode | mã số cho phép toán, tương ứng với giá trị opcode liệt kê dưới và giá trị bytecode trong bộ sưu tập Opcode. |
| opname | tên đọc được bởi con người cho phép toán |
| arg | đối số số cho phép toán (nếu có), nếu không thì None |
| argval | giá trị arg đã giải quyết (nếu biết), nếu không giống như arg |
| argrepr | mô tả đọc được bởi con người của đối số phép toán |
| offset | chỉ số bắt đầu của phép toán trong chuỗi bytecode |
| starts_line | dòng bắt đầu bởi opcode này (nếu có), nếu không thì None |
| is_jump_target | True nếu code khác nhảy đến đây, nếu không thì False |