此代码有多个单独的问题:
while run:
# loop through each line of user input, adding it to buffer
for line in sys.stdin.readlines():
if line == 'quit':
run = False
首先,您有一个内部循环,直到所有行都被处理后才会结束,即使您在某个时候键入“quit”。设置run = False
不会跳出那个循环。它不会在您键入“quit”后立即退出,而是会继续运行,直到查看完所有行,然后在您在任何时候键入“quit”时退出。
您可以通过break
在run = False
.
但是,不管有没有这个修复,如果你在第一次通过外循环时没有输入“quit”,因为你已经阅读了所有的输入,没有其他东西可以阅读,所以你只会继续运行一个空的内循环一遍又一遍,你永远无法退出。
您有一个循环,意思是“读取并处理所有输入”。你想只做一次。那么,外循环应该是什么?无论如何都不应该;做某事的方法是不使用循环。run
所以,要解决这个问题,摆脱while run:
循环;只需使用内部循环。
然后,如果您键入“quit”,line
实际上将是"quit\n"
,因为readlines
不会删除换行符。
您可以通过测试"quit\n"
或strip
ping 行来修复此问题。
最后,即使你解决了所有这些问题,在做任何事情之前你仍然会永远等待。readlines
返回list
一行。它可能做到这一点的唯一方法是读取所有将出现的行stdin
。在阅读完所有这些行之前,您甚至无法开始循环。
当标准输入是一个文件时,文件结束时会发生这种情况,所以这并不算太糟糕。但是当标准输入是 Windows 命令提示符时,命令提示符永远不会结束。*因此,这需要永远。您不必开始处理行列表,因为等待行列表需要很长时间。
解决方案是不使用readlines()
. 真的,从来没有一个很好的理由来呼吁或不呼吁readlines()
任何事情。stdin
任何可以readlines
工作的东西都已经是一个充满线条的可迭代对象,就像给你的那样list
,readlines
除了它是“懒惰的”:它可以一次给你一个线条,而不是等待并一次给你所有线条。(即使你真的需要这个列表,也可以list(f)
代替f.readlines()
.)
所以,而不是for line in sys.stdin.readlines():
,只是做for line in sys.stdin:
(或者,更好的是,完全替换显式循环并使用一系列迭代器转换,如 mgilson 的回答。)
JBernardo、Wing Tang Wong 等提出的修复都是正确且必要的。他们都没有解决您的问题的原因是,如果您有 4 个错误并修复了 1 个,您的代码仍然无法正常工作。这正是为什么“不起作用”不是衡量编程中任何事情的有用衡量标准的原因,您必须调试实际出了什么问题才能知道您是否正在取得进展。
stdin
*我对永远不会完成有点撒谎。如果您键入 control-Z(您可能需要也可能不需要在它后面加上一个 return),那么stdin
就完成了。但是,如果您的任务是让它在用户键入“quit”< 时立即退出,则只有在用户键入“quit”然后返回时才退出的东西,control-Z,再次返回可能不会被认为是成功的。