printでソースファイルの行番号を出力することを検討しています。
Terminalの3行目に119を出力したいのですが、107になってしまいます。
まだまだ勉強不足と思いますが、修正点をご教示いただける方おられましたら、お願いいたします。
Python
1import inspect 2 3def location(depth=0): 4 # frame = inspect.currentframe(depth+1) 5 frame = inspect.currentframe() 6 return (frame.f_code.co_filename, frame.f_lineno) 7 8# if __name__ == '__main__': 9# def f(): 10# g() 11 12def g(): 13 print(location(1)) 14 # print(location(1)) 15 # print(location(2)) 16 print (117, __file__) 17g() 18print(119, __file__, location())
Terminal
1('test3.py', 107) 2117 test3.py 3119 test3.py ('test3.py', 107)
参考にした記事
inspect --- 活動中のオブジェクトの情報を取得する
Python で現在のファイル名と行番号を調べる。
Pythonのソースファイルの行番号を取得したい
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/11/30 09:42
回答2件
0
本家ドキュメントは参照されているようですが、難しかったでしょうかね。
ソースの元のにしている2番目のリンクは 2010-04-10 と 12年以上前のものなので、仕様が変っています。
3番目も2016と古いのですが仕様は現在と同じです。 でも、使いかたが異なるのですね。
これを直すのはドキュメントに出てくるフレームオブジェクト(スタックフレーム)の知識が要るのでやっかいですね。
元の関数と同じような処理をする関数を作ってみました。
python
1def location(depth=0): 2 frame = inspect.getouterframes(inspect.currentframe())[depth+1] 3 return (frame.filename, frame.lineno)
これでできると思いますよ。
投稿2022/11/30 09:42
総合スコア12657
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/11/30 10:26
2022/11/30 10:37
2022/11/30 10:50
2022/11/30 11:33
2022/11/30 12:11
2022/11/30 12:41
2022/11/30 22:41
2022/12/01 05:09
2022/12/01 05:10
0
実用的な方法ではありませんが、行番号を得る方法の紹介。
コードの実行には python3.9以降を要求。
python
1import ast 2import dis 3import types 4import inspect 5import logging 6import textwrap 7 8logger = logging.getLogger(__name__) 9 10 11## 構文木操作で __lineno__ を行番号に置換する方法 12 13class _ReplaceLineno(ast.NodeTransformer): 14 15 def __init__(self, offset=0): 16 super().__init__() 17 self._offset = offset 18 19 def visit_Name(self, node): 20 if node.id == "__lineno__": 21 return ast.Constant(self._offset + node.lineno) 22 return node 23 24 25def pre(func): 26 offset = func.__code__.co_firstlineno-1 27 src = inspect.getsource(func) 28 src = textwrap.dedent(src) # クラス内メソッドやインナー関数に対応 29 tree = ast.parse(src) 30 tree = ast.fix_missing_locations(_ReplaceLineno(offset).visit(tree)) 31 src = ast.unparse(tree) 32 ctx = {"pre": lambda f:f} 33 exec(src, func.__globals__, ctx) 34 return ctx.get(func.__name__) 35 36 37# ※ 制限: デコレータで処理なので、関数内でないと使えない 38@pre 39def func(): 40 print("static lineno", __lineno__) 41 print(f"static lineno {__lineno__}") 42 43 logger.info(f"HELLO logging reports funcName:lineno") 44 45 46class A: 47 @pre 48 def test(self): 49 print(f"TEST {self} {__lineno__}") 50 51 52 53## 実行時情報 (Frame) から行番号を得る方法 54 55class _GetLineno: 56 def __str__(self) -> str: 57 # ※ 文字列型で返します 58 return str(inspect.currentframe().f_back.f_lineno) 59 60 61__lineno__ = _GetLineno() 62print("dynamic lineno", __lineno__) 63print(f"dynamic lineno {__lineno__}") 64 65 66def main(): 67 func() 68 A().test() 69 70 print("----" * 10) 71 72 # func() 内ではグローバルの __lineno__ が使われていないことを 73 # バイトコードで行番号が埋め込まれているのを確認 LOAD_CONST 74 dis.dis(func) 75 76 # dis.dis(A.test) 77 78 79if __name__ == '__main__': 80 logging.basicConfig( 81 level=logging.DEBUG, 82 # ログ表示に 関数名:行番号 を設定 83 format="%(funcName)s:%(lineno)d %(message)s", 84 ) 85 main() 86
実際の開発では loggingモジュールの利用をお勧めします。
投稿2022/11/30 14:07
総合スコア8664
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/11/30 22:46
2022/12/01 04:11
2022/12/01 09:57
2022/12/01 10:20
2022/12/01 11:13
2022/12/01 14:53
2022/12/01 18:41 編集
2022/12/02 03:28 編集
2022/12/02 04:41
2022/12/02 08:59 編集
2022/12/02 09:29
2022/12/02 09:47
2022/12/02 10:33 編集
2022/12/02 10:56
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。