1. ホーム
  2. python

[解決済み] 関数が呼び出されたときに印刷するにはどうしたらいいですか?

2023-06-19 23:37:19

質問

Python スクリプトをデバッグする際に、プログラム全体のコールスタックを知りたいと思います。 理想的な状況は、Python が呼び出されたときにすべての関数名を表示する Python のコマンドラインフラグがあった場合です (私はチェックした man Python2.7 をチェックしましたが、この種のものは見つかりませんでした)。

このスクリプトでは関数の数が多いので、できれば各関数および/またはクラスの先頭にprintステートメントを追加しない方がいいと思います。

中間的な解決策は、PyDevのデバッガを使用して、いくつかのブレークポイントを置き、私のプログラム内の指定されたポイントのコールスタックをチェックすることでしょう。

もしそのような方法があるならば、私はまだ、プログラムの生涯を通じて呼び出されたすべての関数の完全なリストを見ることを好みます。

どのように解決するのですか?

トレース関数でこれを行うことができます(リターンをトレースし、いくつかの素晴らしいインデントを使用するために、このオリジナルのバージョンを改善したSpacedmanに感謝します)。

def tracefunc(frame, event, arg, indent=[0]):
      if event == "call":
          indent[0] += 2
          print("-" * indent[0] + "> call function", frame.f_code.co_name)
      elif event == "return":
          print("<" + "-" * indent[0], "exit function", frame.f_code.co_name)
          indent[0] -= 2
      return tracefunc

import sys
sys.setprofile(tracefunc)

main()   # or whatever kicks off your script

関数のコードオブジェクトは通常関連する関数と同じ名前を持ちますが、関数は動的に生成されることがあるので、常にそうとは限らないことに注意してください。残念ながら、Pythonはスタック上の関数オブジェクトを追跡しません(私は時々、このためのパッチを提出することを空想していました)。それでも、ほとんどの場合、これは確かに "十分" なのです。

もしこれが問題になるなら、ソース コードから本当の関数名を抽出するか (Python はファイル名と行番号を追跡します)、どの関数オブジェクトがコード オブジェクトを参照しているかをガベージコレクタに確認させることができます。コードオブジェクトを共有する複数の関数が存在する可能性がありますが、それらの名前のどれでも十分によいかもしれません。

4 年後にこれを再検討するために戻ってきたとき、Python 2.6 以降で sys.setprofile() よりも sys.settrace() . 同じトレース関数が使えます。ただ、プロファイル関数は関数が入力または終了したときだけ呼び出されるので、関数の中のものは全速力で実行されます。