nohup で実行した python スクリプトで print した内容がファイルに出力されない時の対処法

前回の記事 のように、一定の時間間隔でAPIから情報を取得し、結果を出力するスクリプトを作成する機会は多い。

import pybitflyer
from time import sleep

api_key = "xxxxxxxxxxxxxxxxxxxx"
api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

api = pybitflyer.API(api_key=api_key, api_secret=api_secret)

while True:
  ticker = api.ticker(product_code=product_code)
  print(ticker)

  sleep(60)

このままターミナルで python script.py を実行すると、APIから取得した内容を60秒毎に出力するが、ターミナルを閉じたり、実行するマシンにSSHで接続している場合は切断したりするとプログラムが終了してしまう。

これを防ぐためには nohup を利用し、バックエンドでスクリプトが実行され続けるようにする。print している内容は out.log に出力させるように指定する。

$ nohup python script.py > out.log &

しかし、実行中にログファイルを開いても、内容が書き込まれていないことがある。これは OS などによって出力がバッファリングされているためで、出力内容をリアルタイムにファイルに書き出すには、明示的にバッファの内容をフラッシュさせる必要がある。

Python で明示的なフラッシュをさせるには sys.stdout.flush を実行する。実行したタイミングで、バッファリングされたデータを標準出力に書き出してくれる。

import sys # flush のために import

while True:
  ticker = api.ticker(product_code=product_code)
  print(ticker)
  sys.stdout.flush() # 明示的にflush

  sleep(60)

もしくは、print の引数として flush=True を追加するとよい。

while True:
  ticker = api.ticker(product_code=product_code)
  print(ticker, flush=True) # 明示的にflush

  sleep(60)