sys.stdin.readlines()背后的原理是什么?

3
问题1: 我有一段像这样的代码(Python2.7):
for line in sys.stdin.readlines():
    print line

当我运行这段代码,输入一个字符串并按下回车键时,什么也没有发生。'print line'没有起作用。因此我想到sys.stdin.readlines()有缓冲,但我想知道它是如何工作的?我能刷新它以便每次给出一行时,'print line'可以立即执行吗?

问题2:这两行代码有什么区别:

for line in sys.stdin:
for line in sys.stdin.readline():

我发现他们的行为有点不同。如果我使用ctrl+D来终止输入,在第一种情况下,我必须按两次ctrl+D才能真正终止。而在第二种情况下,只需要按一次ctrl+D。

1个回答

1

CTRL-D在交互式shell中向stdin发送EOF(文件结束)控制字符。通常,您通过重定向将文件提供给进程的stdin(例如myprogram < myfile),但是如果您正在交互地键入字符到进程的stdin中,则需要告诉它何时停止读取您正在积极创建的“文件”。

sys.stdin.readlines等待stdin完成(通过EOF控制字符),然后方便地将EOF之前整个stdin内容(刷新)拆分为由换行符分隔的标记列表。当您按ENTER键时,您发送一个\n字符,它会为您呈现为新行,但不会告诉stdin停止读取。

关于另外两行,我认为这可能会有所帮助:

sys.stdin 对象视为文件。当你遇到 EOF 时,你保存了该文件,然后不允许再编辑它,因为它已经离开你的手并属于 stdin。你可以对该文件执行函数,如 readlines,这是一个方便的方法,它表示“我想要一个列表,其中每个元素都是该文件中的一行”。或者,你可以使用 readline 从中读取一行,这种情况下 for 循环只会迭代该行中的字符。
在幕后发生了什么?
内部地,对 sys.stdin 的引用会阻塞执行,直到在 sys.stdin 中收到 EOF。然后它变成一个类似文件对象的存储在内存中,并且读指针指向其开头。
当你调用 readline 时,指针读取直到遇到一个 \n 字符,返回刚刚遍历的内容,然后停止在原地等待你再次移动它。再次调用 readline 将导致指针移动到下一个 \n(如果存在),否则是 EOF

readlines命令实际上是让指针从当前位置(不一定是文件开头)开始遍历,直到遇到EOF(换行符\n在功能上没有意义)。

试一试!

尝试操作是学习的最佳方式。

要查看此行为,请创建一个包含10行的文件,然后将其重定向到打印sys.stdin.readline 3次的Python脚本的stdin,然后打印sys.stdin.readlines。您将看到打印出3行,然后是包含7个元素的列表 :)


那么readlines()不是一个生成器吗?readlines()有可能像一个生成器一样工作吗? - LittleSoup
2
No. readlines 相当于说 list(sys.stdin)。如果你使用 for line in sys.stdin,我相信 sys.stdin 被视为一个生成器。在官方文档中搜索文件对象。 - JoshuaRLi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接