print() 方法的語法:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
其中file = sys.stdout的意思是,print函數會將內容打印輸出到標准輸出流(即 sys.stdout),當然也可以自定義輸出流:
with open('test.log', 'a') as f: print('hello world!', file=f) # 內容輸出到了test.log文件中,終端不會打印任何內容
也可以輸出到錯誤輸出流sys.stderr
import sys print('hello world!', file=sys.stderr) # 》》hello world!
其實print函數的默認輸出等價於sys.stdout.write(),只是print會自動換行,而stdout需要手動添加轉義符"\n"
import sys print('hello world!') # 》》hello world! sys.stdout.write('hello world!\n') # 》》hello world!
而print的輸出是否被緩存通常決定於file,但如果flush參數值為True,流會被強制刷新(flush默認為false)。這里需要先看下緩沖是怎么回事
類型 | 說明 | 輸出情況 |
---|---|---|
滿緩沖 | I/O操作只有在緩沖區被填滿之后才會進行 | 1.緩沖區滿 2.刷出數據flush 3.關閉文件 |
行緩沖 | 通常只有遇到換行符時,才會執行實際的I/O操作;但緩沖區滿也會強制執行 | 1.遇到換行符 2.緩沖區滿 3.刷出數據flush 4.關閉文件 |
無緩沖 | 不緩存,直接進行I/O操作 | 直接輸出 |
可以在Python3官方文檔中查到:When interactive, stdout
and stderr
streams are line-buffered. 標准輸出流stdout和錯誤輸出流stderr是行緩沖
那么當file = stdout或者file = stderr時會按照行緩沖的條件輸出到終端,即需要滿足以下其中一個條件才會顯示打印內容:
1. 遇到換行符'\n'
2. 代碼運行結束或緩沖區滿
3. flush = True
現在終於可以看下摘自runoob.com的例子了,print()函數使用 flush 參數生成一個 Loading 的效果:
import time print('---RUNOOB EXAMPLE : Loading 效果---') print('Loading', end='') for i in range(20): print('.', end='', flush=True) time.sleep(0.5)
效果如下圖:
因為print使用end=' '去掉了換行,如果沒有flush=True的話,程序將在最后一次性的打印出結果“Loading....................”
根據前面講述的等效關系,又寫了兩種方法來實現上面的效果
第一種是通過sys.stdout.write()來實現:
import sys import time sys.stdout.write('Loading') for i in range(20): sys.stdout.write('.') sys.stdout.flush() time.sleep(0.5)
第二種是通過sys.stderr.write()來實現,但是差別來了,其實網上隨便查下stderr,會發現大多說它是無緩沖的,據說是從3.7版本之后變成的行緩沖,我用3.7.6版本執行代碼是行緩沖的效果,2.7.10版本確實是無緩沖的效果了
import sys import time sys.stderr.write('Loading') for i in range(20): sys.stderr.write('.') time.sleep(0.5)
無緩沖會直接輸出,便用不着sys.stdout.flush()來強制刷新了