こんにちは、古内です。
今回は少し前にバズった PySnooper で標準出力ではなく、Python としての文字列として取得する方法をご紹介します。
はじめに
以下が、経緯です。
また、公式ドキュメントが整っておらず、文字列を取得するやり方について見つからなかったので記事にしました。
コード自体はかなり適当に作られています。
本番環境で恒久的に運用することはしないでください。
この記事では、以下のバージョンでのご紹介になります。
- Python: 3.7.2
- PySnooper: 0.0.39
読者の想定
- Python 構文が分かる人
- 手っ取り早く PySnooper の文字列を Slack 等に送りつけたい人
- New Relic 等がどうしても使えない環境でボトルネックをチェックしたい人
ソースコード
正直、記事にするか悩むレベルで簡単です。( ドキュメントなかったのでとりあえず記事にしましたが… )
class MyWritableStream(pysnooper.utils.WritableStream):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.dump_message = ''
def write(self, s: str) -> None:
self.dump_message += s
はい、ほぼこれだけです。
あとは使うだけ。
ws = MyWritableStream()
with pysnooper.snoop(output=ws):
num1 = 1
num2 = 2
result = num1 + num2
print(ws.dump_message) # ws.dump_message で文字列として取得できる
あなたのデバッグしたいコードを with pysnooper.snoop(output=ws):
の中に突っ込んでください。
例では num1 = 1
から result = num1 + num2
部分です。
そして、最後に print(ws.dump_message)
部分を Slack なりメールなり、ログファイルなりにすればいいと思います。
解説のしようがないレベルであれなので必要なことだけ列挙しておきます。
- pysnooper.utils.WritableStream を継承したクラスを作って write メソッドオーバーライドする
- with 構文で snoop する際に引数に予め初期化しておいた WritableStream インスタンスを渡す
以上です。
注意としてはデコレータでの使用は難しいって感じですかね。
理由としては WritableStream の初期化が問題です。
( デコレーターで試してませんが多分だめだと思います )
あとがき
なんだかすごく内容の薄い記事になってしまいました。
そのうち PySnooper もどんどん整備されていけばこういった記事がなくても良くなると思います。
ですが、WritableStream について触れている文献も探すの面倒だったりしたのでやっちゃいました。
こうした方がいいよとか、間違いとかあればぜひご指摘お願いします。
ありがとうございました!