毫無疑問, print
函數是我們日常最常用的函數,無論是格式化輸出還是列印中間變數進行偵錯,幾乎沒有 print
接不了的活兒。
但是上一次阿醬就差點被 print
給坑了。
最初是想要為自己的一個命令列小工具增加一個進度顯示功能,於是用了 threading
模組來實現多執行緒,一個執行緒用於執行實際的邏輯,另一個執行緒用於列印當前進度。
根據我們
多年 使用命令列的經驗,一般列印進度都是在行內列印,而Python的 print
則會預設在結尾列印一個換行符,這就十分不美了。
不過好在, print
也提供了介面來改變列印的末尾字元,通過指定 print
的 end
引數,即可改變 print
的列印結果。
所以我就哼哧哼哧地開幹了,把列印進度的 print("#")
呼叫改為 print("#", end="")
。
類似這樣:
哪成想,這麼一改卻出了大問題:進度沒法實時列印了。
也就是說,本來應該在程式執行期間,挨個列印出來的 #
號不再是聽話的、可愛的 #
號了,而是在整個程式執行完成之後一次性輸出到控制檯中。
它長大了, 也變醜了 。
那我要你有何用?
一開始阿醬以為是多執行緒出了問題,傻乎乎地到處找資料來「佐證」自己的各種猜測——事後想來實在太傻了,以至於現在說起還是會哈哈哈
這件事給我們的教訓就是: 千萬不要自以為是,而應踏踏實實地解決問題,虛心對待每個細節 。
實際上,之所以我們看不到實時的輸出,就是因為我們改變了 print
的結尾字元。
為了儘量減少I/O操作,Python存在一個這樣的機制:儘量將輸出字元快取起來,當遇到字串結束、換行符或強制重新整理緩衝區時,才會一次性將緩衝區的內容輸出到相應的流中。
——而我們改掉的地方,就是把 print
預設的換行符去掉了,所以原本每一個 print
都會觸發一次緩衝區重新整理,變成了現在一直觸發不了緩衝區重新整理,直到程式結束觸發一次。
好嘛,知道了啥問題,我們又吭哧吭哧找資料,聽說 sys.stdout.flush
可以強制觸發標準輸出緩衝區的重新整理,於是在 print
後面,緊跟著又加上了 sys.stdout.flush()
。
誒?還真好了?
這些可都是知識點,快記下來記下來,要考的
讓我們檢視 print
的官方檔案,其原型為:
根據其下的描述,Python中 print
的輸出是否進行緩衝,取決於兩個引數: file
和 flush
。
file
的型別有的需要緩衝,比如 sys.stdout
;而有的則不需要緩衝,比如 sys.stderr
。
對於 flush
引數,當其值為 False
(預設)時,是否緩衝依賴 file
;而當其值為 True
時,則會強制重新整理緩衝區。
我們把範例呼叫中的 print
呼叫修改一下:
同樣可以實現進度的實時列印。
此外,還有一種方法,在呼叫程式時增加一個 -u
選項,也可以實現緩衝區的實時重新整理:
當然這種方法就不太推薦了,畢竟不能對程式的使用者作任何預設。
本文是阿醬的一次踩坑實錄,記錄了Python中一個很少有人會遇到的奇葩問題。
總的來說,要想成為一個真正的Python程式設計師,只是單純掌握基本語法和一些奇技淫巧是遠遠不夠的,還是需要對Python本身有一定的瞭解。
畢竟,劍客如果不熟悉自己的劍,又該如何行走江湖呢?
相關免費學習推薦:
以上就是使用Python時多少有人走過的坑!避險!的詳細內容,更多請關注TW511.COM其它相關文章!