2017-04-05 7 views
-1

私のPythonプログラムでスクリーン印刷をフィルタリングしたいと思います。Pythonのスクリーン印刷をどのようにフィルタリングできますか?

理想的には、このような「ブラックリストを印刷する」を指定するとよいでしょう。

*FutureWarning* 
INFO* 

画面印刷出力の一部は、上記のパターンのいずれかと一致する場合、全体のプリントアウトが除外されています。

これは非常に便利だと思うので、誰もこの質問をまだ聞いていないことに驚いています。それがなければ、さまざまなタイプのスクリーン印刷を行い、それに応じて対処する必要があるからです。あなたはそれらのいくつかがprintwarningなどによるものがあると想像することができます。

私はbashからPythonスクリプトを実行していますので、bashベースの方法も歓迎です!

+1

「スクリーン印刷」とはどういう意味ですか?あなたの説明は、シンビオント出力デバイス(多くの場合、コマンドウィンドウ)にさまざまなチャネルを通じて出力されたメッセージを参照しているようですが、用語が一致しません。あなたの半分の例は、確かめるために十分な詳細を与えておらず、質問の形式はSOの特異性基準と実際には一致しません。 – Prune

+0

私は多分彼が 'grep -v -E"(リストの|ブラックリストに載せられた|単語)のようなものを探していると思うかもしれません " – mbarkhau

答えて

1

私のPythonプログラムでスクリーン印刷をフィルタリングしたいと思います。

あなたはそれを介してすべての印刷と警告出力をルーティング、Pythonのloggingモジュールを使用することができます。これにより

# in your main module 
import logging 

# -- log all output to myapp.log 
logging.basicConfig(filename='myapp.log', level=logging.DEBUG) 
# -- OR log all output to console 
logging.basicConfig(level=logging.DEBUG) 
# route all output to logging 
logging.captureWarnings(True) 
print = logging.info 

を必須のキーワードごとに、すべての出力をフィルタリングするFilterあなた自身を追加します。

# define Filter in its own module, say logfilter.py 
class OutputFilter(logging.Filter): 
    def __init__(self, keywords, name=None): 
     super(OutputFilter, self).__init__(name) 
     self.keywords = keywords 

    def filter(self, record): 
     msg = record.getMessage() 
     return not any(k in msg for k in self.keywords) 

# add this in your main module 
from logfilter import OutputFilter 
flt = OutputFilter(['*FutureWarning*', 'INFO*']) 
logger = logging.getLogger() # root logger 
logger.addFilter(flt) 
warnLogger = logging.getLogger('py.warnings') # warnings logger 
warnLogger.addFilter(flt) 

(...)それがなければ、さまざまな種類のスクリーン印刷を行い、それに応じて対処する必要があります。

あなたはいつもの代わりに、印刷のモジュールのロガーを使用することをお勧めしますソースコードを変更することができる場合:

# in any module with output, right after imports 
logger = logging.getLogger(__name__) 
... 
# instead of print 
logger.info(...) 
logger.error(...) 
logger.debug(...) 

利点はloggingであるあなたに何を出力し、どこに非常にきめの細かい制御が可能になります、すべてを中央の場所から構成します。

たとえば、すべてのロギング出力に適用されるルートロガーを使用していますが、アプリケーションのすべてのモジュールに独自のロガーを設定することができます。他のすべての出力が端末になりながら、この例では、ファイルmyapp-A.logへのルートモジュールAによってすべてINFOメッセージを意志

# somewhere in your main module 
# -- basic config is to console 
logging.basicConfig(level=logging.DEBUG) 
# -- module A output should go into its own file 
logger = logging.getLogger('path.to.module.A') 
handler = logging.FileHandler(filename='myapp-A.log') # see above 
logger.setHandler(handler) 
logger.setLevel(logging.INFO) 

# path/to/module/A.py 
# -- right at the top of the module 
import logging 
logger = logging.getLogger(__name__) 
... 
# in the actual code 
logger.info('info message') 

注:すべての例はPython Logging Cookbookから採用されています。さらに詳細な説明についてはtutorialをご覧ください。

1

print変数は、表示したくない出力をチェックするカスタム関数にバインドできます。ここで

は一例です:あなたはbashの操作を行うために喜んでいる

>>> def print(*args, **kwargs): 
...  import builtins 
...  if not any(str(s).startswith('INFO') for s in args): 
...    builtins.print(*args, **kwargs) 
+0

ありがとう!しかし、 'print'以外のコマンドがあって、何かを印刷したらどうでしょうか? –

+2

@SibbsGambling 'sys.stdout'を' io.TextIOWrapper'をサブクラス化するカスタムオブジェクトで置き換えることができますが、私はそれをお勧めしません。他の答えをチェックしてください。 – Rishav

1

言います。あなたが別のスクリプトを書くことができ、filter.pyを言う:

from sys import stdin 

def print_filtered(line): 
    if line.startswith("print this"): 
     print(line, end='') # The line includes its own newline character 

for line in stdin: 
    print_filtered(line) 

はもちろん、あなたがprint_filtered()で好きなフィルタリングオプションを置くことができます。あなたはいくつかの置換えをすることさえできます。文字列の一部を削除する場合は、その前に文字列の部分を削除することをお勧めします。

今、あなたは、出力をフィルタリングしているしたい任意のプログラムは、あなたがこのように実行することができます

$ python myfile.py | python filter.py 

Rishavも、カスタムオブジェクトにsys.stdoutを置き換えることができることを彼のコメントで述べました。私は実際にそのアイデア好きではないが、あなたはこのような何かをすることを行うことができます:

import sys 

class FilteredPrinter(object): 
    def __init__(self, filtered_print, stdout): 
     self._filtered_print = filtered_print 
     self._stdout = stdout 

    def _write(self, string): 
     self._filtered_print(string, self._stdout) 

    def __getattr__(self, attr): 
     if attr == 'write': 
      return self._write 
     return getattr(self._stdout, attr) 


def filtered_print(string, stdout): 
    if string == "\n" or string.startswith("print this"): 
     stdout.write(string) 

sys.stdout = FilteredPrinter(filtered_print, sys.stdout) 
print("print this: my text") 
print("print this text") 
print("Don't print this") 

このソリューションでは、あなたが好きなフィルタを指定することができます。 sys.stderrでこれを行うこともできます。あなたが古いものに戻る場合は、sys.stdout = sys.stdout._stdoutを使用してください。 print関数は、それぞれの引数に対して1回、改行文字に対して1回、を呼び出します。

sys.stdout.write("first") 
sys.stdout.write(" ") 
sys.stdout.write("second") 
sys.stdout.write("\n") 

だから、あなたのフィルタ機能を書くときに心の中でそれを保つようにしてください:それはprint("first", "second")はこれを行います呼び出す、です。

+0

+1ありがとう!しかし、 'python myfile.py | python filter.py '' myfile.py'の後に 'filter.py'を実行しますか?その時、物事はすでにスクリーンに印刷されていますか?私の場合、 'myfile.py'は長時間実行されるスクリプトであり、常に画面に表示されます。 –

+0

@sibbs:出力はパイプされているので、myfilter.pyが出力しない限り、出力されません。私は本当にmyfilter.pyがリアルタイムでそれを処理すると確信していますが、テストを実行することができます。 – zondo

+0

うん、それは私が 'cmd =" python myfile.py | python filter.py "したからです。 eval $ {cmd} '?リアルタイムで印刷を停止することはありません。 –

関連する問題