非阻塞模式下sys.stdin.read(10)返回值逻辑的技术问询
非阻塞模式下sys.stdin.read(10)返回值逻辑的技术问询
能不能请大家帮我解释下这段代码里sys.stdin.read(10)的返回值逻辑呀?我对照官方文档推导了半天,实在理不清头绪,卡进死胡同了。
import sys, os os.set_blocking(sys.stdin.fileno(), False) c = sys.stdin.read(10) print(c)
下面是我从上到下的推导过程,肯定哪里出了问题,最后越想越乱:
- 首先,根据文档描述,
sys.stdin属于“和open()返回的类似的常规文本文件”,所以我推断它是一个TextIOWrapper对象。 - 关于
TextIOWrapper,文档里是这样定义的:一个提供高级访问能力的缓冲文本流,基于
BufferedIOBase缓冲二进制流构建,继承自TextIOBase。 - 所有
io.TextIO相关的文档都没有区分阻塞和非阻塞模式,特别是io.TextIOBase.read(size=-1, /)的方法说明:读取并返回最多size个字符的字符串。如果size为负数或None,会持续读取直到遇到EOF。
- 接着看
BufferedIOBase的文档,里面提到像read()这类方法的行为:[...] 如果底层原始流处于非阻塞模式,且无法读取或写入足够数据时,可能会抛出
BlockingIOError。 - 更让我困惑的是,我在CPython里发现
sys.stdout.buffer是存在的,它是BufferedReader对象(继承自BufferedIOBase),而io.BufferedReader.read(size=-1, /)的文档说明是:读取并返回size字节的数据;如果没有指定size或size为负数,会读取到EOF,或者在非阻塞模式下如果调用会导致阻塞的话就停止读取。
(顺带提一句,我英语不太好,不太理解“非阻塞模式下如果调用会导致阻塞的话就停止读取”这种情况到底会返回什么内容。) - 最后,我查了PEP3116,里面提到(注意原文的
IOError现在已经被OSError替代了):在缓冲I/O和文本I/O层,如果读写操作因为非阻塞条件失败,会抛出一个
IOError,且errno设为EAGAIN。
现在我就懵了:BufferedIOBase说“可能会抛出”异常,PEP3116明确说“会抛出”异常,但BufferedReader的文档里不仅没提抛异常,反而说会停止读取。这几个文档的描述看起来互相矛盾,到底sys.stdin.read(10)在非阻塞模式下的返回值逻辑应该是怎样的呀?
备注:内容来源于stack exchange,提问作者JtTest
相关产品推荐
相关产品推荐

