これは非常にばかげたことであり、ほとんどの人はそれを行うことはできないと言うでしょう (THC4k は、一般的なケースでこれの説得力のある証拠を提供します)。
ステップ1。フレームをさかのぼる必要があります。sys._getframe
orを使用して最初のものを取得しinspect.currentframe
ます (誰にも言わないでください。2 番目は最初のエイリアスのようです)。次に、それらを反復処理できますf.f_back
ステップ2。それぞれにf.f_lasti
指示があります。これは、フレームで実行された最後の命令です。保存する必要があります。次に、バイトコードをさかのぼって - f.f_code.co_code
- f.f_lasti` の後SETUP_EXCEPT
にジャンプする引数を持つオペコードを探します。分岐点は例外処理です。
ステップ3。これは、より曖昧になるところです。重要なのは、実際の比較演算はCOMPARE_OP
、引数として 10 を持つ a になるということです。私が見たすべてのケースで、その後にPOP_JUMP_IF_FALSE
. except
これにより、次の節または節にジャンプしfinally
ます。例外をスタックにロードするコードが先行します。1 つしかない場合は、ストレートLOAD_GLOBAL
またはLOAD_GLOBAL
or LOAD_FAST
(例外のあるモジュールがグローバルかローカルかによって異なります) の後にLOAD_ATTR
. 一致する例外が複数ある場合は、一連のロード操作の後にBUILD_TUPLE
(慣用的な) またはBUILD_LIST
(その他の奇妙な状況または非慣用的な状況) が続きます。
ポイントは、LOAD_X
手順を確認して、名前と一致する例外を比較できることです。name のみを比較していることに注意してください。彼らが名前を再割り当てした場合、あなたは SOL です。
ステップ4。一致が見つかったとしましょう。次に、関数オブジェクトが必要です。これを行うために私が考えることができる最良の方法は次のとおりです (私は更新する権利を留保します):f.f_code
にはco_filename
属性があります。ループすることができsys.modules
、それぞれに__name__
属性があります。を使用する必要があることを念頭に置いて、2 つを比較できます__name__.endswith(co_filename)
。一致すると、モジュール関数をループして、それらのf.func_code.co_firstlineno
属性をフレームと比較できますf.f_lineno
属性。試合に勝てば、自分の役割を果たします。モジュール内の各クラスのメソッドもループする必要があります。ネストされた関数で処理が発生している可能性があります。その場合、私は現在、賢明なことを考えることはできません。(それはまったく別のバイトコードのハックであり、それ自体が不安定になります)
ステップ5。利益。
これにより、これを行う方法の一般的なアイデアが得られるはずです。あなたがそれを行うことができないあらゆる種類のコーナーケースがありますが、通常のユースケースでは、それをやってのけることができるはずです. それができることに依存するコードを書くと、それは壊れます。これは一種の「できるからやる」ということです。