4

大規模なコードベースに依存するプログラムがあり、無関係で迷惑なメッセージを大量に出力します。それらを少しクリーンアップしたいのですが、それらのコンテンツは動的に生成されるため、単にgrepすることはできません。

印刷ステートメントにフックを配置する方法はありますか?(私はPython 2.4を使用していますが、どのバージョンの結果にも興味があります)。出力がどの「印刷」ステートメントから来るかを見つける別の方法はありますか?

4

5 に答える 5

3

厳密に言えば、ライブラリのように、依存しているコードベースにはステートメントを含めるべきではありませ print。したがって、実際にはそれらをすべて削除する必要があります。

それ以外に、モンキーパッチを適用できstdoutます:Pythonプリントに日時スタンプを追加する

于 2012-11-22T14:46:33.557 に答える
3

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.currentframeusesに注意してください。sys._getframeしたがって、上記のソリューションはCPythonでのみ機能する可能性があります。

于 2012-11-22T15:30:27.420 に答える
2

これを機能させるための非常に大まかなハック:

お気に入りのテキストエディタを使用し、検索/検索機能を使用します。

すべての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が必要な場合に備えて、基本的なインクリメントクラスを使用しました。

于 2012-11-22T14:44:54.053 に答える
1

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)
于 2012-11-22T14:50:02.887 に答える
1

過酷な状況(いくつかの奇妙なバイナリライブラリで出力が行われる)では、strace -e write(およびより多くのオプション)を使用することもできます。straceの出力を読み取らない場合、stracedプログラムは読み取るまで待機するため、シグナルを送信して、どこで終了するかを確認できます。

于 2012-11-22T16:33:00.510 に答える