Pythonのループ内でsleep関数とprint()を併用すると一つ一つ表示されないとき

Pythonで席替えプログラムを作成時に困ったことを書いておく。

困ったこと

10人分(実際はN人)の席順を表示するときに、1秒ごとに一つずつ席を表示させたかったので以下のようにした。

for i, student in enumerate(students):
    if i % 7 == 0:
        print()

    print("{0:3d}|".format(student), end=' ')
    time.sleep(1)

しかし、この状態だと、10秒後(10人 * 1秒) に一気に表示されるだけで、一つずつ出てくれない。

原因

ドキュメント*1によると、printは

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)¶

がデフォルトで設定されているらしい。 ここで、flushを見てみよう。

flush

通常、出力処理はタイミングを見計らって出力をするバッファリングを行う。 そのため、flushを使って、バッファリングしている結果を出力させる。

Pythonでは、改行(\n)ごとに自動的にflushされている。*2

しかし、今回は終端文字をスペースにしていたため、自動的にflushがされなかったので、一気に表示される動作が起こった。

結論

引数のflushをTrueに変えてあげると、毎回表示をしてくれる。

for i, student in enumerate(students):
    if i % 7 == 0:
        print()

    print("{0:3d}|".format(student), end='', flush = True)
    time.sleep(1)

参考文献