关于python:关于python的IO读写的二三事

42次阅读

共计 3212 个字符,预计需要花费 9 分钟才能阅读完成。

IO 读写内幕

对于 io 读写,能够分为缓存 io 与间接 io 两种。而前者缓存 io 是以后最为罕用的一种 io 机制:即应用缓冲区 buffer(内存中的一块地址),来避免对硬件的频繁拜访,由此缩小读写操作的工夫耗费和硬件自身的耗费。

缓存 io:
基于操作系统将硬件与用户程序分隔的思维,实现上会在内核空间创立一个 buffer,在读操作时,操作系统会把数据从硬件读入内核空间的 buffer,用户过程再从内核空间的 buffer 复制到本人的用户空间(应用程序地址空间)中,之后若是再次读取会去查看内核空间中的 buffer 区,缩小与硬件的 io 次数。同样对于写操作,也是先把用户空间中的内容写到内核空间中,应用程序不必期待,零碎主动把内核空间 buffer 中的内容写入磁盘。

tips:
具体来说,在用户空间中,也是会指定一段内存空间来寄存从内核 buffer 读取来的数据,咱们也能够称之为用户空间的 buffer 区。这样用户应用程序每次读写肯定数据,不须要每次都间接与内核空间进行通信,能够先存放在用户空间的 buffer 中一段时间,能够缩小用户空间与内核空间之间的通信次数,即缩小零碎调用次数,肯定水平上缩小开销。(不过个别未显著指定,buffer 都是指的内核空间的 buffer

advantage:

  • 缓存 io 应用了操作系统内核缓冲区,在肯定水平上拆散了应用程序空间和理论的物理设施,更平安。
  • 缓存 io 能够缩小读盘的次数,从而进步性能。

disadvantage:

  • 内核空间和用户空间之间频繁的数据拷贝也会对 CPU 以及内存造成较大的开销。

间接 io 简介:
间接 io 就是勾销内核空间中的 buffer 缓冲区,数据间接从硬件传输到用户空间。这样能够缩小内核缓冲区到用户程序缓存的数据复制操作的开销。

较典型的利用场景如数据库管理系统这类利用,它们更偏向于抉择它们本人的缓存机制,因为数据库管理系统往往比操作系统更理解数据库中寄存的数据,数据库管理系统能够提供一种更加无效的缓存机制来进步数据库中数据的存取性能。

间接 io 的毛病:如果拜访的数据不在应用程序缓存中,那么每次数据都会间接从磁盘加载,这种间接加载会十分缓存。通常间接 io 与异步 io 联合应用,会失去比拟好的性能。(异步 io:当拜访数据的线程发出请求之后,线程会接着去解决其余事,而不是阻塞期待)

以上只是简略地介绍了一下 io 机制,实际上的 io 机制是更简单的,能够参考以下文章对其深刻理解一下:
缓存 io,间接 io,内存映射
linux 中间接 io 机制介绍
io 读写原理

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.

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。

正文完
 0