dis
— Python 位元組碼反彙編器¶
原始碼: Lib/dis.py
dis
模組支援透過反彙編來分析 CPython 位元組碼 。此模組作為輸入的 CPython 位元組碼在檔案 Include/opcode.h
中定義,並由編譯器和直譯器使用。
CPython 實現細節: 位元組碼是 CPython 直譯器的實現細節。不保證位元組碼在 Python 版本之間不會被新增、刪除或更改。本模組的使用不應被認為可以在不同的 Python 虛擬機器或 Python 版本之間工作。
在 3.6 版本中更改: 每條指令使用 2 個位元組。以前位元組數因指令而異。
在 3.10 版本中更改: 跳轉、異常處理和迴圈指令的引數現在是指令偏移而不是位元組偏移。
在 3.11 版本中更改: 一些指令會伴隨一個或多個內聯快取條目,這些條目採用 CACHE
指令的形式。這些指令預設是隱藏的,但是可以透過傳遞 show_caches=True
到任何 dis
實用程式來顯示。此外,直譯器現在會調整位元組碼以針對不同的執行時條件進行專門化。可以透過傳遞 adaptive=True
來顯示自適應位元組碼。
在 3.13 版本中更改: 輸出顯示跳轉目標和異常處理程式的邏輯標籤,而不是指令偏移量。添加了 -O
命令列選項和 show_offsets
引數。
例如:給定函式 myfunc()
def myfunc(alist):
return len(alist)
可以使用以下命令來顯示 myfunc()
的反彙編
>>> dis.dis(myfunc)
2 RESUME 0
3 LOAD_GLOBAL 1 (len + NULL)
LOAD_FAST 0 (alist)
CALL 1
RETURN_VALUE
(“2” 是行號)。
命令列介面¶
可以從命令列將 dis
模組作為指令碼呼叫
python -m dis [-h] [-C] [-O] [infile]
接受以下選項
- -h, --help¶
顯示用法並退出。
- -C, --show-caches¶
顯示內聯快取。
- -O, --show-offsets¶
顯示指令的偏移量。
如果指定了 infile
,則其反彙編程式碼將被寫入 stdout。否則,將對從 stdin 接收的已編譯原始碼執行反彙編。
位元組碼分析¶
3.4 版本新增。
位元組碼分析 API 允許將 Python 程式碼片段包裝在 Bytecode
物件中,該物件提供對已編譯程式碼細節的輕鬆訪問。
- class dis.Bytecode(x, *, first_line=None, current_offset=None, show_caches=False, adaptive=False, show_offsets=False)¶
分析與函式、生成器、非同步生成器、協程、方法、原始碼字串或程式碼物件(由
compile()
返回)相對應的位元組碼。這是對下面列出的許多函式的便捷包裝,最值得注意的是
get_instructions()
,因為迭代Bytecode
例項會生成位元組碼操作作為Instruction
例項。如果 first_line 不是
None
,則表示應為反彙編程式碼中的第一個原始碼行報告的行號。否則,原始碼行資訊(如果有)直接取自反彙編程式碼物件。如果 current_offset 不是
None
,則它指的是反彙編程式碼中的指令偏移量。設定此項意味著dis()
將在指定的 opcode 上顯示“當前指令”標記。如果 show_caches 為
True
,則dis()
將顯示直譯器用於專門化位元組碼的內聯快取條目。如果 adaptive 為
True
,則dis()
將顯示可能與原始位元組碼不同的專門化位元組碼。如果 show_offsets 為
True
,則dis()
將在輸出中包含指令偏移量。- classmethod from_traceback(tb, *, show_caches=False)¶
從給定的回溯構造一個
Bytecode
例項,將 current_offset 設定為導致異常的指令。
- codeobj¶
編譯後的程式碼物件。
- first_line¶
程式碼物件的第一個原始碼行(如果可用)
- info()¶
返回包含有關程式碼物件的詳細資訊的格式化多行字串,如
code_info()
。
在 3.7 版本中更改: 現在可以處理協程和非同步生成器物件。
在 3.11 版本中更改: 添加了 show_caches 和 adaptive 引數。
示例
>>> bytecode = dis.Bytecode(myfunc)
>>> for instr in bytecode:
... print(instr.opname)
...
RESUME
LOAD_GLOBAL
LOAD_FAST
CALL
RETURN_VALUE
分析函式¶
dis
模組還定義了以下分析函式,它們直接將輸入轉換為所需的輸出。如果只執行一個操作,那麼中間的分析物件就沒什麼用處,這些函式就很有用。
- dis.code_info(x)¶
返回一個格式化的多行字串,其中包含為提供的函式、生成器、非同步生成器、協程、方法、原始碼字串或程式碼物件提供的詳細程式碼物件資訊。
請注意,程式碼資訊字串的確切內容高度依賴於實現,並且它們可能會在 Python VM 或 Python 版本之間任意更改。
3.2 版本新增。
在 3.7 版本中更改: 現在可以處理協程和非同步生成器物件。
- dis.show_code(x, *, file=None)¶
將提供的函式、方法、原始碼字串或程式碼物件的詳細程式碼物件資訊列印到 file(如果未指定 file,則列印到
sys.stdout
)。這是
print(code_info(x), file=file)
的便捷簡寫,旨在用於直譯器提示符下的互動式探索。3.2 版本新增。
在 3.4 版本中更改: 添加了 file 引數。
- dis.dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False)¶
反彙編 x 物件。 x 可以表示模組、類、方法、函式、生成器、非同步生成器、協程、程式碼物件、原始碼字串或原始位元組碼的位元組序列。 對於模組,它會反彙編所有函式。 對於類,它會反彙編所有方法(包括類方法和靜態方法)。 對於程式碼物件或原始位元組碼序列,它會為每個位元組碼指令列印一行。 它還會遞迴地反彙編巢狀的程式碼物件。 這些可以包括生成器表示式、巢狀函式、巢狀類的主體以及用於註解作用域的程式碼物件。 字串首先使用
compile()
內建函式編譯為程式碼物件,然後再進行反彙編。 如果未提供任何物件,則此函式會反彙編最後一個回溯。反彙編以文字形式寫入提供的 file 引數(如果提供),否則寫入
sys.stdout
。遞迴的最大深度受 depth 限制,除非它是
None
。depth=0
表示不遞迴。如果 show_caches 為
True
,此函式將顯示直譯器用於專門化位元組碼的內聯快取條目。如果 adaptive 為
True
,此函式將顯示可能與原始位元組碼不同的專用位元組碼。在 3.4 版本中更改: 添加了 file 引數。
在 3.7 版本中更改: 實現了遞迴反彙編並添加了 depth 引數。
在 3.7 版本中更改: 現在可以處理協程和非同步生成器物件。
在 3.11 版本中更改: 添加了 show_caches 和 adaptive 引數。
- distb(tb=None, *, file=None, show_caches=False, adaptive=False,
- show_offset=False)
反彙編回溯的堆疊頂層函式,如果沒有傳遞迴溯,則使用最後一個回溯。 指示導致異常的指令。
反彙編以文字形式寫入提供的 file 引數(如果提供),否則寫入
sys.stdout
。在 3.4 版本中更改: 添加了 file 引數。
在 3.11 版本中更改: 添加了 show_caches 和 adaptive 引數。
在 3.13 版本中更改: 添加了 show_offsets 引數。
- dis.disassemble(code, lasti=-1, *, file=None, show_caches=False, adaptive=False)¶
- disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False,
- show_offsets=False)
反彙編程式碼物件,如果提供了 lasti,則指示最後一條指令。 輸出分為以下幾列:
行號,對於每行的第一條指令
當前指令,指示為
-->
,標記的指令,指示為
>>
,指令的地址,
操作碼名稱,
操作引數,以及
括號中引數的解釋。
引數解釋識別區域性和全域性變數名、常量值、分支目標和比較運算子。
反彙編以文字形式寫入提供的 file 引數(如果提供),否則寫入
sys.stdout
。在 3.4 版本中更改: 添加了 file 引數。
在 3.11 版本中更改: 添加了 show_caches 和 adaptive 引數。
在 3.13 版本中更改: 添加了 show_offsets 引數。
- dis.get_instructions(x, *, first_line=None, show_caches=False, adaptive=False)¶
返回提供的函式、方法、原始碼字串或程式碼物件中指令的迭代器。
迭代器生成一系列
Instruction
命名元組,其中提供了所提供程式碼中每個操作的詳細資訊。如果 first_line 不是
None
,則表示應為反彙編程式碼中的第一個原始碼行報告的行號。否則,原始碼行資訊(如果有)直接取自反彙編程式碼物件。adaptive 引數的工作方式與
dis()
中相同。3.4 版本新增。
在 3.11 版本中更改: 添加了 show_caches 和 adaptive 引數。
在 3.13 版本中更改: show_caches 引數已棄用,不起作用。 迭代器生成具有 cache_info 欄位填充的
Instruction
例項(無論 show_caches 的值如何),並且它不再為快取條目生成單獨的項。
- dis.findlinestarts(code)¶
此生成器函式使用
co_lines()
方法的 程式碼物件 code 來查詢原始碼中行開始的偏移量。 它們以(offset, lineno)
對的形式生成。在 3.6 版本中更改: 行號可能會遞減。 以前,它們總是遞增的。
在 3.10 版本中更改: 使用 PEP 626
co_lines()
方法,而不是co_firstlineno
和co_lnotab
屬性的 程式碼物件。在 3.13 版本中更改: 對於不對映到原始碼行的位元組碼,行號可以為
None
。
- dis.findlabels(code)¶
檢測原始編譯位元組碼字串 code 中所有作為跳轉目標的偏移量,並返回這些偏移量的列表。
- dis.stack_effect(opcode, oparg=None, *, jump=None)¶
計算具有引數 oparg 的 opcode 的堆疊效應。
如果程式碼具有跳轉目標並且jump為
True
,則stack_effect()
將返回跳轉的堆疊效應。如果 jump 為False
,它將返回不跳轉的堆疊效應。如果 jump 為None
(預設值),它將返回兩種情況的最大堆疊效應。3.4 版本新增。
在 3.8 版本中更改: 添加了 jump 引數。
在 3.13 版本中更改: 如果省略
oparg
(或None
),現在將返回oparg=0
的堆疊效應。之前,對於使用其引數的操作碼,這是一個錯誤。當opcode
不使用oparg
時,傳遞整數oparg
也不再是錯誤;在這種情況下,oparg
將被忽略。
Python 位元組碼指令¶
get_instructions()
函式和 Bytecode
類以 Instruction
例項的形式提供位元組碼指令的詳細資訊
- class dis.Instruction¶
位元組碼操作的詳細資訊
- opname¶
操作的人類可讀名稱
- arg¶
操作的數字引數(如果有),否則為
None
- argval¶
已解析的引數值(如果有),否則為
None
- argrepr¶
操作引數的人類可讀描述(如果有),否則為空字串。
- offset¶
操作在位元組碼序列中的起始索引
- cache_offset¶
操作之後的快取條目的起始索引
- end_offset¶
操作之後的快取條目的結束索引
- starts_line¶
如果此操作碼開始一個原始碼行,則為
True
,否則為False
- line_number¶
與此操作碼關聯的原始碼行號(如果有),否則為
None
- is_jump_target¶
如果有其他程式碼跳轉到此處,則為
True
,否則為False
- jump_target¶
如果這是一個跳轉操作,則為跳轉目標的位元組碼索引,否則為
None
- positions¶
儲存此指令覆蓋的起始和結束位置的
dis.Positions
物件。
3.4 版本新增。
在 3.11 版本中更改: 添加了
positions
欄位。在 3.13 版本中更改: 更改了
starts_line
欄位。添加了欄位
start_offset
、cache_offset
、end_offset
、baseopname
、baseopcode
、jump_target
、oparg
、line_number
和cache_info
。
- class dis.Positions¶
如果資訊不可用,某些欄位可能為
None
。- lineno¶
- end_lineno¶
- col_offset¶
- end_col_offset¶
在 3.11 版本中新增。
Python 編譯器當前生成以下位元組碼指令。
通用指令
在下面,我們將直譯器堆疊稱為 STACK
,並描述對其的操作,就好像它是一個 Python 列表一樣。堆疊的頂部對應於此語言中的 STACK[-1]
。
- NOP¶
無操作程式碼。用作位元組碼最佳化器的佔位符,並生成行跟蹤事件。
- POP_TOP¶
刪除堆疊頂部的專案
STACK.pop()
- END_FOR¶
刪除堆疊頂部的專案。等效於
POP_TOP
。用於在迴圈結束時清理,因此得名。在 3.12 版本中新增。
- END_SEND¶
實現
del STACK[-2]
。用於在生成器退出時清理。在 3.12 版本中新增。
- COPY(i)¶
將第 i 個專案推送到堆疊頂部,而無需將其從原始位置刪除
assert i > 0 STACK.append(STACK[-i])
在 3.11 版本中新增。
- SWAP(i)¶
將堆疊頂部與第 i 個元素交換
STACK[-i], STACK[-1] = STACK[-1], STACK[-i]
在 3.11 版本中新增。
- CACHE¶
此操作碼並非實際指令,而是用於標記額外的空間,供直譯器直接在位元組碼本身中快取有用的資料。它會被所有
dis
實用工具自動隱藏,但可以使用show_caches=True
檢視。從邏輯上講,此空間是前一條指令的一部分。許多操作碼都期望後跟確切數量的快取,並會指示直譯器在執行時跳過這些快取。
填充的快取可能看起來像任意指令,因此在讀取或修改包含加速資料的原始自適應位元組碼時應格外小心。
在 3.11 版本中新增。
一元運算
一元運算會獲取堆疊頂部的值,應用運算,並將結果推回堆疊。
- UNARY_NEGATIVE¶
實現
STACK[-1] = -STACK[-1]
。
- UNARY_INVERT¶
實現
STACK[-1] = ~STACK[-1]
。
- GET_ITER¶
實現
STACK[-1] = iter(STACK[-1])
。
- GET_YIELD_FROM_ITER¶
如果
STACK[-1]
是一個 生成器迭代器 或 協程 物件,則保持不變。否則,實現STACK[-1] = iter(STACK[-1])
。在 3.5 版本中新增。
- TO_BOOL¶
實現
STACK[-1] = bool(STACK[-1])
。在 3.13 版本中新增。
二元和原地操作
二元運算會從堆疊中移除頂部的兩個項(STACK[-1]
和 STACK[-2]
)。它們執行運算,然後將結果放回堆疊。
原地運算類似於二元運算,但當 STACK[-2]
支援時,運算會在原地完成,並且生成的 STACK[-1]
可以是(但不一定必須是)原始的 STACK[-2]
。
- BINARY_OP(op)¶
實現二元和原地運算子(取決於 op 的值)
rhs = STACK.pop() lhs = STACK.pop() STACK.append(lhs op rhs)
在 3.11 版本中新增。
- BINARY_SUBSCR¶
實現
key = STACK.pop() container = STACK.pop() STACK.append(container[key])
- STORE_SUBSCR¶
實現
key = STACK.pop() container = STACK.pop() value = STACK.pop() container[key] = value
- DELETE_SUBSCR¶
實現
key = STACK.pop() container = STACK.pop() del container[key]
- BINARY_SLICE¶
實現
end = STACK.pop() start = STACK.pop() container = STACK.pop() STACK.append(container[start:end])
在 3.12 版本中新增。
- STORE_SLICE¶
實現
end = STACK.pop() start = STACK.pop() container = STACK.pop() values = STACK.pop() container[start:end] = value
在 3.12 版本中新增。
協程操作碼
- GET_AWAITABLE(where)¶
實現
STACK[-1] = get_awaitable(STACK[-1])
,其中如果o
是協程物件或具有CO_ITERABLE_COROUTINE
標誌的生成器物件,則get_awaitable(o)
返回o
,或解析o.__await__
。如果
where
運算元非零,則表示指令出現的位置1
: 在呼叫__aenter__
之後2
: 在呼叫__aexit__
之後
在 3.5 版本中新增。
在 3.11 版本中更改: 以前,此指令沒有運算元。
- GET_AITER¶
實現
STACK[-1] = STACK[-1].__aiter__()
。在 3.5 版本中新增。
在 3.7 版本中更改: 不再支援從
__aiter__
返回可等待物件。
- GET_ANEXT¶
將
STACK.append(get_awaitable(STACK[-1].__anext__()))
實現到堆疊。有關get_awaitable
的詳細資訊,請參閱GET_AWAITABLE
。在 3.5 版本中新增。
- END_ASYNC_FOR¶
終止
async for
迴圈。處理等待下一個項時引發的異常。堆疊包含STACK[-2]
中的非同步可迭代物件和STACK[-1]
中引發的異常。兩者都會被彈出。如果異常不是StopAsyncIteration
,則會重新引發。在 3.8 版本中新增。
在 3.11 版本中更改: 堆疊上的異常表示現在由一項而不是三項組成。
- CLEANUP_THROW¶
處理在當前幀中透過
throw()
或close()
呼叫期間引發的異常。如果STACK[-1]
是StopIteration
的例項,則從堆疊中彈出三個值並推送其value
成員。否則,重新引發STACK[-1]
。在 3.12 版本中新增。
- BEFORE_ASYNC_WITH¶
從
STACK[-1]
解析__aenter__
和__aexit__
。將__aexit__
和__aenter__()
的結果推送到堆疊STACK.extend((__aexit__, __aenter__())
在 3.5 版本中新增。
雜項操作碼
- SET_ADD(i)¶
實現
item = STACK.pop() set.add(STACK[-i], item)
用於實現集合推導式。
- LIST_APPEND(i)¶
實現
item = STACK.pop() list.append(STACK[-i], item)
用於實現列表推導式。
- MAP_ADD(i)¶
實現
value = STACK.pop() key = STACK.pop() dict.__setitem__(STACK[-i], key, value)
用於實現字典推導式。
在 3.1 版本中新增。
在 3.8 版本中更改: 對映值為
STACK[-1]
,對映鍵為STACK[-2]
。之前,它們是反向的。
對於所有 SET_ADD
、LIST_APPEND
和 MAP_ADD
指令,在新增的值或鍵/值對被彈出時,容器物件仍然保留在堆疊上,以便在迴圈的進一步迭代中可用。
- RETURN_VALUE¶
將
STACK[-1]
返回給函式的呼叫者。
- RETURN_CONST(consti)¶
將
co_consts[consti]
返回給函式的呼叫者。在 3.12 版本中新增。
- YIELD_VALUE¶
從 生成器 中產生
STACK.pop()
。在 3.11 版本中更改: oparg 設定為堆疊深度。
在 3.12 版本中更改: oparg 設定為異常塊深度,以便高效關閉生成器。
在 3.13 版本中更改: 如果此指令是 yield-from 或 await 的一部分,則 oparg 為
1
,否則為0
。
- SETUP_ANNOTATIONS¶
檢查
__annotations__
是否在locals()
中定義,如果未定義,則將其設定為一個空的dict
。只有當類或模組主體靜態包含變數註解時,才會發出此操作碼。在 3.6 版本中加入。
- POP_EXCEPT¶
從堆疊中彈出一個值,用於恢復異常狀態。
在 3.11 版本中更改: 堆疊上的異常表示現在由一項而不是三項組成。
- RERAISE¶
重新引發當前在堆疊頂部的異常。如果 oparg 非零,則從堆疊中彈出一個附加值,該值用於設定當前幀的
f_lasti
。在 3.9 版本中加入。
在 3.11 版本中更改: 堆疊上的異常表示現在由一項而不是三項組成。
- PUSH_EXC_INFO¶
從堆疊中彈出一個值。將當前異常推送到堆疊頂部。將最初彈出的值推回堆疊。用於異常處理程式中。
在 3.11 版本中新增。
- CHECK_EXC_MATCH¶
為
except
執行異常匹配。測試STACK[-2]
是否是一個與STACK[-1]
匹配的異常。彈出STACK[-1]
並推送測試的布林結果。在 3.11 版本中新增。
- CHECK_EG_MATCH¶
為
except*
執行異常匹配。在表示STACK[-2]
的異常組上應用split(STACK[-1])
。如果匹配,則從堆疊中彈出兩項,並推送不匹配的子組(如果完全匹配,則為
None
),後跟匹配的子組。如果沒有匹配,則彈出一項(匹配型別)並推送None
。在 3.11 版本中新增。
- WITH_EXCEPT_START¶
呼叫堆疊位置 4 中的函式,其引數 (type, val, tb) 表示堆疊頂部的異常。用於實現當
with
語句中發生異常時呼叫context_manager.__exit__(*exc_info())
。在 3.9 版本中加入。
在 3.11 版本中更改:
__exit__
函式位於堆疊的位置 4,而不是位置 7。堆疊上的異常表示現在由一項組成,而不是三項。
- LOAD_ASSERTION_ERROR¶
將
AssertionError
推送到堆疊上。由assert
語句使用。在 3.9 版本中加入。
- LOAD_BUILD_CLASS¶
將
builtins.__build_class__()
推送到堆疊上。稍後將呼叫它來構造一個類。
- BEFORE_WITH¶
此操作碼在 with 程式碼塊開始之前執行多個操作。首先,它從上下文管理器中載入
__exit__()
,並將其推送到堆疊上,供WITH_EXCEPT_START
稍後使用。然後,呼叫__enter__()
。最後,將呼叫__enter__()
方法的結果推送到堆疊上。在 3.11 版本中新增。
- MATCH_MAPPING¶
如果
STACK[-1]
是collections.abc.Mapping
的例項(或者,更準確地說:如果其tp_flags
中設定了Py_TPFLAGS_MAPPING
標誌),則將True
推送到堆疊上。否則,推送False
。在 3.10 版本中加入。
- MATCH_SEQUENCE¶
如果
STACK[-1]
是collections.abc.Sequence
的例項,並且不是str
/bytes
/bytearray
的例項(或者,更準確地說:如果其tp_flags
中設定了Py_TPFLAGS_SEQUENCE
標誌),則將True
推送到堆疊上。否則,推送False
。在 3.10 版本中加入。
- MATCH_KEYS¶
STACK[-1]
是對映鍵的元組,STACK[-2]
是匹配主體。如果STACK[-2]
包含STACK[-1]
中的所有鍵,則推送一個包含相應值的tuple
。否則,推送None
。在 3.10 版本中加入。
在 3.11 版本中更改:以前,此指令還會推送一個布林值,指示成功 (
True
) 或失敗 (False
)。
- STORE_NAME(namei)¶
實現
name = STACK.pop()
。namei 是co_names
屬性中 name 的索引,該屬性是程式碼物件。編譯器會嘗試儘可能使用STORE_FAST
或STORE_GLOBAL
。
- UNPACK_SEQUENCE(count)¶
將
STACK[-1]
解包為 count 個單獨的值,這些值從右到左放入堆疊。要求必須恰好有 count 個值。assert(len(STACK[-1]) == count) STACK.extend(STACK.pop()[:-count-1:-1])
- UNPACK_EX(counts)¶
使用帶星號的目標實現賦值:將
STACK[-1]
中的可迭代物件解包為單獨的值,其中值的總數可以小於可迭代物件中的項數:其中一個新值將是所有剩餘項的列表。列表值之前和之後的值的數量限制為 255。
列表值之前的數值個數編碼在操作碼的引數中。列表之後的數值個數(如果有)使用
EXTENDED_ARG
進行編碼。因此,該引數可以被視為一個兩位元組的值,其中 counts 的低位元組表示列表值之前的數值個數,counts 的高位元組表示列表值之後的數值個數。提取的值會以從右到左的順序放入堆疊,即
a, *b, c = d
在執行後將儲存為STACK.extend((a, b, c))
。
- STORE_ATTR(namei)¶
實現
obj = STACK.pop() value = STACK.pop() obj.name = value
- STORE_GLOBAL(namei)¶
與
STORE_NAME
的工作方式相同,但將名稱儲存為全域性名稱。
- DELETE_GLOBAL(namei)¶
與
DELETE_NAME
的工作方式相同,但刪除全域性名稱。
- LOAD_CONST(consti)¶
將
co_consts[consti]
壓入堆疊。
- LOAD_NAME(namei)¶
將與
co_names[namei]
關聯的值壓入堆疊。該名稱首先在區域性變數中查詢,然後在全域性變數中查詢,最後在內建變數中查詢。
- LOAD_LOCALS¶
將對區域性變數字典的引用壓入堆疊。這用於為
LOAD_FROM_DICT_OR_DEREF
和LOAD_FROM_DICT_OR_GLOBALS
準備名稱空間字典。在 3.12 版本中新增。
- LOAD_FROM_DICT_OR_GLOBALS(i)¶
從堆疊中彈出一個對映,並查詢
co_names[namei]
的值。如果在那裡找不到該名稱,則會在全域性變數中查詢,然後再在內建變數中查詢,類似於LOAD_GLOBAL
。這用於在類主體內的 註釋作用域 中載入全域性變數。在 3.12 版本中新增。
- BUILD_TUPLE(count)¶
建立一個元組,從堆疊中消耗 count 個項,並將結果元組壓入堆疊
if count == 0: value = () else: value = tuple(STACK[-count:]) STACK = STACK[:-count] STACK.append(value)
- BUILD_LIST(count)¶
與
BUILD_TUPLE
的工作方式相同,但建立一個列表。
- BUILD_SET(count)¶
與
BUILD_TUPLE
的工作方式相同,但建立一個集合。
- BUILD_MAP(count)¶
將一個新的字典物件壓入堆疊。彈出
2 * count
個項,以便字典包含 count 個條目:{..., STACK[-4]: STACK[-3], STACK[-2]: STACK[-1]}
。3.5 版本更改: 該字典是從堆疊項建立的,而不是建立一個預先調整大小以容納 count 個項的空字典。
- BUILD_CONST_KEY_MAP(count)¶
BUILD_MAP
的專門用於常量鍵的版本。彈出堆疊頂部的元素,該元素包含一個鍵的元組,然後從STACK[-2]
開始,彈出 count 個值以形成構建的字典中的值。在 3.6 版本中加入。
- BUILD_STRING(count)¶
從堆疊中連線 count 個字串,並將結果字串壓入堆疊。
在 3.6 版本中加入。
- LIST_EXTEND(i)¶
實現
seq = STACK.pop() list.extend(STACK[-i], seq)
用於構建列表。
在 3.9 版本中加入。
- SET_UPDATE(i)¶
實現
seq = STACK.pop() set.update(STACK[-i], seq)
用於構建集合。
在 3.9 版本中加入。
- DICT_UPDATE(i)¶
實現
map = STACK.pop() dict.update(STACK[-i], map)
用於構建字典。
在 3.9 版本中加入。
- DICT_MERGE(i)¶
與
DICT_UPDATE
類似,但對於重複的鍵會引發異常。在 3.9 版本中加入。
- LOAD_ATTR(namei)¶
如果
namei
的低位未設定,則此操作會將STACK[-1]
替換為getattr(STACK[-1], co_names[namei>>1])
。如果
namei
的低位已設定,則將嘗試從STACK[-1]
物件載入名為co_names[namei>>1]
的方法。彈出STACK[-1]
。此位元組碼區分兩種情況:如果STACK[-1]
具有正確名稱的方法,則位元組碼將壓入未繫結方法和STACK[-1]
。當呼叫未繫結方法時,STACK[-1]
將被用作CALL
或CALL_KW
的第一個引數(self
)。否則,將壓入NULL
和屬性查詢返回的物件。3.12 版本更改: 如果
namei
的低位已設定,則在屬性或未繫結方法之前,將NULL
或self
壓入堆疊。
- LOAD_SUPER_ATTR(namei)¶
此操作碼實現
super()
,包括其零引數形式和雙引數形式(例如,super().method()
,super().attr
和super(cls, self).method()
,super(cls, self).attr
)。它從堆疊中彈出三個值(從堆疊頂部向下):
self
: 當前方法的第一個引數cls
: 定義當前方法的類全域性變數
super
關於它的引數,它的工作方式類似於
LOAD_ATTR
,除了namei
向左移動 2 位而不是 1 位。namei
的低位表示嘗試載入方法,就像LOAD_ATTR
一樣,這會導致壓入NULL
和載入的方法。如果未設定,則將單個值壓入堆疊。如果設定了
namei
的第二低位,則表示這是對super()
的雙引數呼叫(未設定表示零引數呼叫)。在 3.12 版本中新增。
- COMPARE_OP(opname)¶
執行布林運算。 運算名稱可以在
cmp_op[opname >> 5]
中找到。 如果設定了opname
的第五低位 (opname & 16
),則結果應強制轉換為bool
。在 3.13 版本中變更:現在,運算元的第五低位表示強制轉換為
bool
。
- IS_OP(invert)¶
執行
is
比較,如果invert
為 1,則執行is not
比較。在 3.9 版本中加入。
- CONTAINS_OP(invert)¶
執行
in
比較,如果invert
為 1,則執行not in
比較。在 3.9 版本中加入。
- IMPORT_NAME(namei)¶
匯入模組
co_names[namei]
。STACK[-1]
和STACK[-2]
被彈出,並提供__import__()
的 *fromlist* 和 *level* 引數。模組物件被壓入堆疊。當前名稱空間不受影響:對於正確的匯入語句,後續的STORE_FAST
指令會修改名稱空間。
- IMPORT_FROM(namei)¶
從
STACK[-1]
中找到的模組載入屬性co_names[namei]
。 結果物件被壓入堆疊,隨後由STORE_FAST
指令儲存。
- JUMP_FORWARD(delta)¶
將位元組碼計數器增加 *delta*。
- JUMP_BACKWARD(delta)¶
將位元組碼計數器減少 *delta*。檢查中斷。
在 3.11 版本中新增。
- JUMP_BACKWARD_NO_INTERRUPT(delta)¶
將位元組碼計數器減少 *delta*。不檢查中斷。
在 3.11 版本中新增。
- POP_JUMP_IF_TRUE(delta)¶
如果
STACK[-1]
為 true,則將位元組碼計數器增加 *delta*。STACK[-1]
被彈出。在 3.11 版本中變更:運算元現在是一個相對增量,而不是絕對目標。此操作碼是一個偽指令,在最終位元組碼中被定向版本(向前/向後)替換。
在 3.12 版本中變更:這不再是偽指令。
在 3.13 版本中更改: 此指令現在要求一個精確的
bool
運算元。
- POP_JUMP_IF_FALSE(delta)¶
如果
STACK[-1]
為 false,則將位元組碼計數器增加 *delta*。STACK[-1]
被彈出。在 3.11 版本中變更:運算元現在是一個相對增量,而不是絕對目標。此操作碼是一個偽指令,在最終位元組碼中被定向版本(向前/向後)替換。
在 3.12 版本中變更:這不再是偽指令。
在 3.13 版本中更改: 此指令現在要求一個精確的
bool
運算元。
- POP_JUMP_IF_NOT_NONE(delta)¶
如果
STACK[-1]
不是None
,則將位元組碼計數器增加 *delta*。STACK[-1]
被彈出。此操作碼是一個偽指令,在最終位元組碼中被定向版本(向前/向後)替換。
在 3.11 版本中新增。
在 3.12 版本中變更:這不再是偽指令。
- POP_JUMP_IF_NONE(delta)¶
如果
STACK[-1]
是None
,則將位元組碼計數器增加 *delta*。STACK[-1]
被彈出。此操作碼是一個偽指令,在最終位元組碼中被定向版本(向前/向後)替換。
在 3.11 版本中新增。
在 3.12 版本中變更:這不再是偽指令。
- FOR_ITER(delta)¶
STACK[-1]
是一個 迭代器。呼叫其__next__()
方法。如果這產生一個新值,則將其壓入堆疊(將迭代器留在其下方)。如果迭代器指示它已耗盡,則將位元組碼計數器增加 *delta*。在 3.12 版本中變更:在 3.11 版本之前,迭代器在耗盡時會被彈出。
- LOAD_GLOBAL(namei)¶
將名為
co_names[namei>>1]
的全域性變數載入到堆疊上。在 3.11 版本中變更:如果設定了
namei
的低位,則在全域性變數之前將NULL
推入堆疊。
- LOAD_FAST(var_num)¶
將對區域性變數
co_varnames[var_num]
的引用推入堆疊。在 3.12 版本中變更:此操作碼現在僅用於保證區域性變數已初始化的情形。它不能引發
UnboundLocalError
。
- LOAD_FAST_LOAD_FAST(var_nums)¶
將對
co_varnames[var_nums >> 4]
和co_varnames[var_nums & 15]
的引用推入堆疊。在 3.13 版本中新增。
- LOAD_FAST_CHECK(var_num)¶
將對區域性變數
co_varnames[var_num]
的引用推入堆疊,如果區域性變數未初始化,則引發UnboundLocalError
。在 3.12 版本中新增。
- LOAD_FAST_AND_CLEAR(var_num)¶
將對區域性變數
co_varnames[var_num]
的引用推入堆疊(如果區域性變數未初始化,則將NULL
推入堆疊),並將co_varnames[var_num]
設定為NULL
。在 3.12 版本中新增。
- STORE_FAST(var_num)¶
將
STACK.pop()
儲存到區域性變數co_varnames[var_num]
中。
- STORE_FAST_STORE_FAST(var_nums)¶
將
STACK[-1]
儲存到co_varnames[var_nums >> 4]
中,並將STACK[-2]
儲存到co_varnames[var_nums & 15]
中。在 3.13 版本中新增。
- STORE_FAST_LOAD_FAST(var_nums)¶
將
STACK.pop()
儲存到區域性變數co_varnames[var_nums >> 4]
中,並將對區域性變數co_varnames[var_nums & 15]
的引用推入堆疊。在 3.13 版本中新增。
- DELETE_FAST(var_num)¶
刪除區域性變數
co_varnames[var_num]
。
- MAKE_CELL(i)¶
在槽位
i
中建立一個新單元格。如果該槽位非空,則將該值儲存到新單元格中。在 3.11 版本中新增。
- LOAD_DEREF(i)¶
載入“快速區域性變數”儲存區槽位
i
中包含的單元格。將單元格中包含的物件的引用推送到堆疊上。在 3.11 版本中更改:
i
不再被co_varnames
的長度偏移。
- LOAD_FROM_DICT_OR_DEREF(i)¶
從堆疊中彈出一個對映,並在該對映中查詢與“快速區域性變數”儲存區槽位
i
關聯的名稱。如果該名稱未在此處找到,則從槽位i
中包含的單元格載入,類似於LOAD_DEREF
。這用於在類主體中(之前使用LOAD_CLASSDEREF
)和類主體內的註解作用域中載入閉包變數。在 3.12 版本中新增。
- STORE_DEREF(i)¶
將
STACK.pop()
儲存到“快速區域性變數”儲存區槽位i
中包含的單元格中。在 3.11 版本中更改:
i
不再被co_varnames
的長度偏移。
- DELETE_DEREF(i)¶
清空“快速區域性變數”儲存區槽位
i
中包含的單元格。由del
語句使用。3.2 版本新增。
在 3.11 版本中更改:
i
不再被co_varnames
的長度偏移。
- RAISE_VARARGS(argc)¶
根據 argc 的值,使用
raise
語句的 3 種形式之一引發異常0:
raise
(重新引發先前的異常)1:
raise STACK[-1]
(在STACK[-1]
處引發異常例項或型別)2:
raise STACK[-2] from STACK[-1]
(在STACK[-2]
處引發異常例項或型別,並將__cause__
設定為STACK[-1]
)
- CALL(argc)¶
使用
argc
指定的引數數量呼叫可呼叫物件。堆疊上的內容(按升序排列)為:可呼叫物件
self
或NULL
其餘的位置引數
argc
是位置引數的總數,不包括self
。CALL
會將所有引數和可呼叫物件從堆疊中彈出,使用這些引數呼叫可呼叫物件,並將可呼叫物件返回的返回值推送到堆疊上。在 3.11 版本中新增。
在 3.13 版本中更改: 可呼叫物件現在始終出現在堆疊上的相同位置。
在 3.13 版本中更改: 帶有關鍵字引數的呼叫現在由
CALL_KW
處理。
- CALL_KW(argc)¶
使用
argc
指定的引數數量(包括一個或多個命名引數)呼叫可呼叫物件。堆疊上的內容(按升序排列)為:可呼叫物件
self
或NULL
其餘的位置引數
命名引數
關鍵字引數名稱的
tuple
argc
是位置引數和命名引數的總數,不包括self
。關鍵字引數名稱的元組的長度是命名引數的數量。CALL_KW
會將所有引數、關鍵字名稱和可呼叫物件從堆疊中彈出,使用這些引數呼叫可呼叫物件,並將可呼叫物件返回的返回值推送到堆疊上。在 3.13 版本中新增。
- CALL_FUNCTION_EX(flags)¶
使用可變的一組位置引數和關鍵字引數呼叫可呼叫物件。如果 flags 的最低位已設定,則堆疊的頂部包含一個對映物件,其中包含其他關鍵字引數。在呼叫可呼叫物件之前,對映物件和可迭代物件都會被“解包”,它們的內容分別作為關鍵字引數和位置引數傳遞。
CALL_FUNCTION_EX
會將所有引數和可呼叫物件從堆疊中彈出,使用這些引數呼叫可呼叫物件,並將可呼叫物件返回的返回值推送到堆疊上。在 3.6 版本中加入。
- PUSH_NULL¶
將
NULL
推送到堆疊。在呼叫序列中用於匹配LOAD_METHOD
為非方法呼叫推送的NULL
。在 3.11 版本中新增。
- MAKE_FUNCTION¶
在堆疊上推送從
STACK[-1]
處的程式碼物件構建的新函式物件。在 3.10 版本中更改: 標誌值
0x04
是字串元組而不是字典在 3.11 版本中更改: 刪除了
STACK[-1]
處的限定名稱。在 3.13 版本中更改: 刪除了堆疊上的額外函式屬性,這些屬性由操作碼標誌發出訊號。它們現在使用
SET_FUNCTION_ATTRIBUTE
。
- SET_FUNCTION_ATTRIBUTE(flag)¶
在函式物件上設定屬性。 預期
STACK[-1]
處的函式和要在STACK[-2]
處設定的屬性值;消耗兩者,並在STACK[-1]
處保留函式。該標誌確定要設定哪個屬性0x01
按位置順序排列的僅限位置和位置或關鍵字引數的預設值元組0x02
僅限關鍵字引數的預設值的字典0x04
包含引數註釋的字串元組0x08
包含自由變數單元格的元組,構成一個閉包
在 3.13 版本中新增。
- BUILD_SLICE(argc)¶
在堆疊上推送一個切片物件。argc 必須為 2 或 3。如果為 2,則實現
end = STACK.pop() start = STACK.pop() STACK.append(slice(start, end))
如果為 3,則實現
step = STACK.pop() end = STACK.pop() start = STACK.pop() STACK.append(slice(start, end, step))
有關更多資訊,請參閱
slice()
內建函式。
- EXTENDED_ARG(ext)¶
為任何引數太大而無法放入預設的一個位元組的操作碼新增字首。ext 儲存一個額外的位元組,該位元組充當引數中的高位。對於每個操作碼,最多允許三個字首
EXTENDED_ARG
,從而形成從兩位元組到四位元組的引數。
- CONVERT_VALUE(oparg)¶
根據
oparg
將值轉換為字串value = STACK.pop() result = func(value) STACK.append(result)
用於實現格式化的文字字串(f-字串)。
在 3.13 版本中新增。
- FORMAT_SIMPLE¶
格式化堆疊頂部的值
value = STACK.pop() result = value.__format__("") STACK.append(result)
用於實現格式化的文字字串(f-字串)。
在 3.13 版本中新增。
- FORMAT_WITH_SPEC¶
使用給定的格式規範格式化給定值
spec = STACK.pop() value = STACK.pop() result = value.__format__(spec) STACK.append(result)
用於實現格式化的文字字串(f-字串)。
在 3.13 版本中新增。
- MATCH_CLASS(count)¶
STACK[-1]
是關鍵字屬性名稱的元組,STACK[-2]
是要匹配的類,而STACK[-3]
是匹配的主題。count 是位置子模式的數量。彈出
STACK[-1]
、STACK[-2]
和STACK[-3]
。如果STACK[-3]
是STACK[-2]
的例項,並且具有 count 和STACK[-1]
所要求的位置屬性和關鍵字屬性,則壓入一個提取的屬性元組。否則,壓入None
。在 3.10 版本中加入。
在 3.11 版本中更改:以前,此指令還會推送一個布林值,指示成功 (
True
) 或失敗 (False
)。
- RESUME(context)¶
空操作。執行內部跟蹤、除錯和最佳化檢查。
context
運算元由兩部分組成。最低兩位表示RESUME
發生的位置0
函式的開始,既不是生成器、協程也不是非同步生成器1
在yield
表示式之後2
在yield from
表示式之後3
在await
表示式之後
如果 RESUME 處於 except-depth
1
,則下一位為1
,否則為0
。在 3.11 版本中新增。
在 3.13 版本中更改: oparg 值已更改,以包含有關 except-depth 的資訊
- RETURN_GENERATOR¶
從當前幀建立一個生成器、協程或非同步生成器。用作上述可呼叫物件的程式碼物件中的第一個操作碼。清除當前幀並返回新建立的生成器。
在 3.11 版本中新增。
- SEND(delta)¶
等效於
STACK[-1] = STACK[-2].send(STACK[-1])
。用於yield from
和await
語句中。如果呼叫引發
StopIteration
,則從堆疊中彈出頂部值,壓入異常的value
屬性,並將位元組碼計數器增加 delta。在 3.11 版本中新增。
- HAVE_ARGUMENT¶
這實際上不是一個操作碼。它標識了範圍 [0,255] 中不使用其引數的操作碼和使用其引數的操作碼(分別為
< HAVE_ARGUMENT
和>= HAVE_ARGUMENT
)之間的分界線。如果你的應用程式使用偽指令或專用指令,請改用
hasarg
集合。在 3.6 版本中更改: 現在每個指令都有一個引數,但操作碼
< HAVE_ARGUMENT
會忽略它。之前,只有操作碼>= HAVE_ARGUMENT
有一個引數。在 3.12 版本中更改: 偽指令已新增到
dis
模組中,對於它們來說,與HAVE_ARGUMENT
的比較並不表示它們是否使用其引數。自 3.13 版本起已棄用: 請改用
hasarg
。
- CALL_INTRINSIC_1¶
呼叫一個帶有一個引數的內部函式。將
STACK[-1]
作為引數傳遞,並將STACK[-1]
設定為結果。用於實現非效能關鍵的功能。運算元決定呼叫哪個內部函式
運算元
描述
INTRINSIC_1_INVALID
無效
INTRINSIC_PRINT
將引數列印到標準輸出。在 REPL 中使用。
INTRINSIC_IMPORT_STAR
對命名模組執行
import *
。INTRINSIC_STOPITERATION_ERROR
從
StopIteration
異常中提取返回值。INTRINSIC_ASYNC_GEN_WRAP
包裝一個非同步生成器值
INTRINSIC_UNARY_POSITIVE
執行一元
+
運算INTRINSIC_LIST_TO_TUPLE
將列表轉換為元組
INTRINSIC_TYPEVAR
建立一個
typing.TypeVar
INTRINSIC_PARAMSPEC
建立一個
typing.ParamSpec
INTRINSIC_TYPEVARTUPLE
建立一個
typing.TypeVarTuple
INTRINSIC_SUBSCRIPT_GENERIC
返回以引數下標的
typing.Generic
INTRINSIC_TYPEALIAS
建立一個
typing.TypeAliasType
;在type
語句中使用。引數是類型別名的名稱、型別引數和值的元組。在 3.12 版本中新增。
- CALL_INTRINSIC_2¶
呼叫一個帶有兩個引數的內部函式。用於實現非效能關鍵的功能
arg2 = STACK.pop() arg1 = STACK.pop() result = intrinsic2(arg1, arg2) STACK.append(result)
運算元決定呼叫哪個內部函式
運算元
描述
INTRINSIC_2_INVALID
無效
INTRINSIC_PREP_RERAISE_STAR
計算從
try-except*
引發的ExceptionGroup
。INTRINSIC_TYPEVAR_WITH_BOUND
建立一個帶有邊界的
typing.TypeVar
。INTRINSIC_TYPEVAR_WITH_CONSTRAINTS
建立一個帶有約束的
typing.TypeVar
。INTRINSIC_SET_FUNCTION_TYPE_PARAMS
設定函式的
__type_params__
屬性。在 3.12 版本中新增。
偽指令
這些操作碼不會出現在 Python 位元組碼中。它們由編譯器使用,但在生成位元組碼之前會被真實的操作碼替換或刪除。
- SETUP_FINALLY(target)¶
為以下程式碼塊設定異常處理程式。如果發生異常,則將值堆疊級別恢復到其當前狀態,並將控制權轉移到
target
處的異常處理程式。
- SETUP_CLEANUP(target)¶
類似於
SETUP_FINALLY
,但如果發生異常,還會將最後一條指令(lasti
)壓入堆疊,以便RERAISE
可以恢復它。如果發生異常,則將值堆疊級別和幀上的最後一條指令恢復到其當前狀態,並將控制權轉移到target
處的異常處理程式。
- SETUP_WITH(target)¶
類似於
SETUP_CLEANUP
,但如果發生異常,則在將控制權轉移到target
處的異常處理程式之前,還會從堆疊中彈出一個專案。此變體用於
with
和async with
構造中,它們將上下文管理器的__enter__()
或__aenter__()
的返回值壓入堆疊。
- POP_BLOCK¶
標記與最後一個
SETUP_FINALLY
、SETUP_CLEANUP
或SETUP_WITH
關聯的程式碼塊的結束。
- JUMP¶
- JUMP_NO_INTERRUPT¶
無方向的相對跳轉指令,由彙編器替換為其有方向(向前/向後)的對應指令。
- LOAD_CLOSURE(i)¶
將對“快速區域性變數”儲存中槽
i
中包含的單元格的引用壓入堆疊。請注意,
LOAD_CLOSURE
在彙編器中被替換為LOAD_FAST
。在 3.13 版本中更改: 此操作碼現在是一個偽指令。
- LOAD_METHOD¶
最佳化的未繫結方法查詢。作為設定了引數標誌的
LOAD_ATTR
操作碼發出。
操作碼集合¶
這些集合用於自動內省位元組碼指令
在 3.12 版本中更改: 這些集合現在也包含偽指令和檢測指令。這些是值 >= MIN_PSEUDO_OPCODE
和 >= MIN_INSTRUMENTED_OPCODE
的操作碼。
- dis.opname¶
操作名稱序列,可使用位元組碼進行索引。
- dis.opmap¶
將操作名稱對映到位元組碼的字典。
- dis.cmp_op¶
所有比較操作名稱的序列。
- dis.hasarg¶
使用其引數的位元組碼序列。
在 3.12 版本中新增。
- dis.hasconst¶
訪問常量的位元組碼序列。
- dis.hasname¶
按名稱訪問屬性的位元組碼序列。
- dis.hasjump¶
具有跳轉目標的位元組碼序列。所有跳轉都是相對的。
在 3.13 版本中新增。
- dis.haslocal¶
訪問區域性變數的位元組碼序列。
- dis.hascompare¶
布林運算的位元組碼序列。
- dis.hasexc¶
設定異常處理程式的位元組碼序列。
在 3.12 版本中新增。
- dis.hasjabs¶
具有絕對跳轉目標的位元組碼序列。
自 3.13 版本起已棄用: 所有跳轉現在都是相對的。此列表為空。