關於python的IO讀寫的二三事

IO讀寫內情

關於io讀寫,能夠分爲緩存io與直接io兩種。而前者緩存io是當前最爲經常使用的一種io機制:即便用緩衝區buffer(內存中的一塊地址),來防止對硬件的頻繁訪問,由此減小讀寫操做的時間消耗和硬件自己的消耗。html

緩存io:
基於操做系統將硬件與用戶程序分隔的思想,實現上會在內核空間建立一個buffer,在讀操做時,操做系統會把數據從硬件讀入內核空間的buffer,用戶進程再從內核空間的buffer複製到本身的用戶空間(應用程序地址空間)中,以後如果再次讀取會去檢查內核空間中的buffer區,減小與硬件的io次數。一樣對於寫操做,也是先把用戶空間中的內容寫到內核空間中,應用程序不用等待,系統自動把內核空間buffer中的內容寫入磁盤。python

tips:
具體來講,在用戶空間中,也是會指定一段內存空間來存放從內核buffer讀取來的數據,咱們也能夠稱之爲用戶空間的buffer區。這樣用戶應用程序每次讀寫必定數據,不須要每次都直接與內核空間進行通訊,能夠先寄存在用戶空間的buffer中一段時間,能夠減小用戶空間與內核空間之間的通訊次數,即減小系統調用次數,必定程度上減小開銷。(不過通常未明顯指定,buffer都是指的內核空間的bufferlinux

advantage:數據庫

  • 緩存io使用了操做系統內核緩衝區,在必定程度上分離了應用程序空間和實際的物理設備,更安全。
  • 緩存io能夠減小讀盤的次數,從而提升性能。

disadvantage:緩存

  • 內核空間和用戶空間之間頻繁的數據拷貝也會對CPU以及內存形成較大的開銷。

直接io簡介:
直接io就是取消內核空間中的buffer緩衝區,數據直接從硬件傳輸到用戶空間。這樣能夠減小內核緩衝區到用戶程序緩存的數據複製操做的開銷。安全

較典型的應用場景如數據庫管理系統這類應用,它們更傾向於選擇它們本身的緩存機制,由於數據庫管理系統每每比操做系統更瞭解數據庫中存放的數據,數據庫管理系統能夠提供一種更加有效的緩存機制來提升數據庫中數據的存取性能。app

直接io的缺點:若是訪問的數據不在應用程序緩存中,那麼每次數據都會直接從磁盤加載,這種直接加載會很是緩存。一般直接io與異步io結合使用,會獲得比較好的性能。(異步io:當訪問數據的線程發出請求以後,線程會接着去處理其餘事,而不是阻塞等待)異步

以上只是簡單地介紹了一下io機制,實際上的io機制是更復雜的,能夠參考如下文章對其深刻了解一下:
緩存io,直接io,內存映射
linux中直接io機制介紹
io讀寫原理ide

python io讀寫

The io module provides Python’s main facilities for dealing with various types of I/O. There are three main types of I/O: text I/O, binary I/O and raw I/O. These are generic categories, and various backing stores can be used for each of them. 函數

A concrete object belonging to any of these categories is called a file object, Other common terms are stream or file-like object.

Independent of its category, each concrete stream object will also have various capabilities: it can be read-only, write-only, or read-write.

All streams are careful about the type of data you give to them. For example giving a str object to the write method of a binary stream will raise a TypeError. So will giving a bytes object to the write() method of a text stream.

對於file object, or stream, or file-like object來講,在io module中對其定義了一些通用的接口,如:read,readline,readlines,write,close,seek,tell,flush等。

open函數

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

  • 對於這裏的buffering參數,所指定的就是內核空間中的buffer大小,能夠參考:python file buffer
  • io.open是該builtin function的一個alias,open函數返回的就是上文所提到的file object, or stream, or file-like object。因此對於open所返回的對象,它也享有那些通用的接口。
  • 對應前文所述的緩存io機制,能夠更深層次理解open函數背後作了什麼。

io.StringIO

io.StringIO(initial_value='')

A text stream using an in-memory text buffer. It inherits TextIOBase.

The text buffer is discarded when the close() method is called.

:該類是用於text讀寫的,即它不支持bytes類型數據的讀寫,對於bytes類型的數據可使用io.BytesIO(initial_bytes=None);另一點由於沒有與硬件進行交互的需求,因此能夠推測該buffer區域是在用戶空間內的,並非在內核空間。

getvalue()
Return a str containing the entire contents of the buffer.

:該方法不會改變stream position的位置,於此相對的是通用的接口read,使用後stream position會像一個指針同樣順着一個個字符的讀取流到buffer的末位。

通用接口

上文的read,readline,readlines,write和close都不用介紹了,在日常對於file object, or stream, or file-like object的操做中,這些都是很經常使用的方法。如下簡單介紹一下:seek,tell,flush這三個method.

seek(offset,whence=SEEK_SET)
Change the stream position to the given byte offset from whence position.

whence value:

  • SEEK_SET or 0 – start of the stream (the default); offset should be zero or positive
  • SEEK_CUR or 1 – current stream position; offset may be negative
  • SEEK_END or 2 – end of the stream; offset is usually negative

tell()
return the current stream position.

tips: with read、seek、tell, you can play with the stream position.

flush()
Flush the write buffers of the stream if applicable.This does nothing for read-only and non-blocking streams-如以前的StringIO使用該方法就是無效的。

:該方法是把buffer中的內容flush進file object相應的文件(硬件設備)中,可是不會影響stream position的位置。平時咱們經常使用的close其實不僅是關閉buffer,它也是先flush,而後再關閉buffer。

對於緩存這個概念的理解:
把數據從not-easy-access的地方移動到easy-access的位置,減小重複讀取所需的開銷。
大於所需的讀入數據到一箇中間性的區域,以後再須要額外的數據能夠直接從中間性區域拿取,而不用再次從數據源讀入。

相關文章
相關標籤/搜索