【Python】關於print()、sys.stdout、sys.stderr的一些理解


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()來強制刷新了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM