大規模なコードベースに依存するプログラムがあり、無関係で迷惑なメッセージを大量に出力します。それらを少しクリーンアップしたいのですが、それらのコンテンツは動的に生成されるため、単にgrepすることはできません。
印刷ステートメントにフックを配置する方法はありますか?(私はPython 2.4を使用していますが、どのバージョンの結果にも興味があります)。出力がどの「印刷」ステートメントから来るかを見つける別の方法はありますか?
大規模なコードベースに依存するプログラムがあり、無関係で迷惑なメッセージを大量に出力します。それらを少しクリーンアップしたいのですが、それらのコンテンツは動的に生成されるため、単にgrepすることはできません。
印刷ステートメントにフックを配置する方法はありますか?(私はPython 2.4を使用していますが、どのバージョンの結果にも興味があります)。出力がどの「印刷」ステートメントから来るかを見つける別の方法はありますか?
厳密に言えば、ライブラリのように、依存しているコードベースにはステートメントを含めるべきではありません print
。したがって、実際にはそれらをすべて削除する必要があります。
それ以外に、モンキーパッチを適用できstdout
ます:Pythonプリントに日時スタンプを追加する
CPython2.5以前の場合:
import sys
import inspect
import collections
_stdout = sys.stdout
Record = collections.namedtuple(
'Record',
'frame filename line_number function_name lines index')
class MyStream(object):
def __init__(self, target):
self.target = target
def write(self, text):
if text.strip():
record = Record(*inspect.getouterframes(inspect.currentframe())[1])
self.target.write(
'{f} {n}: '.format(f = record.filename, n = record.line_number))
self.target.write(text)
sys.stdout = MyStream(sys.stdout)
def foo():
print('Hi')
foo()
収量
/home/unutbu/pybin/test.py 20: Hi
CPython2.6 +の場合、次のコマンドで印刷関数をインポートできます。
from __future__ import print_function
次に、必要に応じてリダイレクトします。
from __future__ import print_function
import sys
import inspect
import collections
Record = collections.namedtuple(
'Record',
'frame filename line_number function_name lines index')
def myprint(text):
if text.strip():
record = Record(*inspect.getouterframes(inspect.currentframe())[1])
sys.stdout.write('{f} {n}: '.format(f = record.filename, n = record.line_number))
sys.stdout.write(text + '\n')
def foo():
print('Hi')
print = myprint
foo()
Pythonのすべての実装の一部ではないinspect.currentframe
usesに注意してください。sys._getframe
したがって、上記のソリューションはCPythonでのみ機能する可能性があります。
これを機能させるための非常に大まかなハック:
お気に入りのテキストエディタを使用し、検索/検索機能を使用します。
すべてのprintステートメントを検索します。
それぞれに番号または識別子を手動で入力します。(または、これを行うと自動的にスクリプトになります)
これを行うためのスクリプトは単純で、print
正規表現で検索し、に置き換えるだけでprint ID,
、すべて同じになりますが、数値が表示されます。
乾杯。
編集
奇妙なフォーマットを除いて、次のコードがあなたのためにそれをするはずです。
これはあなたがそれを行うことができる方法の単なる例であることに注意してください。本当に答えではありません。
import re
class inc():
def __init__(self):
self.x = 0
def get(self):
self.x += 1
return self.x
def replacer(filename_in, filename_out):
i = inc()
out = open(filename_out, 'w')
with open(filename_in) as f:
for line in f:
out.write("%s\n" % re.sub(r'print', 'print %d,' % i.get(), line))
カウンターだけでなく、もっと複雑なIDが必要な場合に備えて、基本的なインクリメントクラスを使用しました。
JeeeyulがJava用に思いついたトリックは次のとおりです。出力ストリーム(つまりsys.out
)を、改行が書き込まれたときに通知されるものに置き換えます。
このフラグがtrueの場合、次のバイトが書き込まれているときに例外をスローします。同じ場所で例外をキャッチし、「デバッグストリームライター」に属していないコードが見つかるまでスタックトレースをたどります。
擬似コード:
class DebugPrintln:
def __init__(self):
self.wasLF = False
def write(self, x):
if self.wasLF:
self.wasLF = False
frames = traceback.extract_stack()
... find calling code and output it ...
if x == '\n':
self.wasLF = true
super.write(x)
過酷な状況(いくつかの奇妙なバイナリライブラリで出力が行われる)では、strace -e write
(およびより多くのオプション)を使用することもできます。straceの出力を読み取らない場合、stracedプログラムは読み取るまで待機するため、シグナルを送信して、どこで終了するかを確認できます。