这段代码存在多个独立的问题:
while run:
for line in sys.stdin.readlines():
if line == 'quit':
run = False
首先,您有一个内部循环,直到所有行都被处理完才结束,即使在某些时候键入“quit”。设置run = False
不能打破该循环。而不是在键入“quit”后立即退出,它会继续进行,直到查看了所有行,然后如果您在任何时候键入“quit”,则退出。
您可以通过在run = False
之后添加break
来轻松解决此问题。
但是,无论是否修复了这个问题,如果您在外部循环的第一次运行中没有输入“退出”,由于您已经读取了所有输入,因此没有其他内容可读取,因此您将永远运行一个空的内部循环,而您永远无法退出。
您有一个循环,意味着“读取并处理所有输入”。您希望仅执行一次。那么,外部循环应该是什么?它不应该是任何方式;做一次事情的方法是不使用循环。因此,要修复此问题,请摆脱run
和while run:
循环;只需使用内部循环即可。
然后,如果您键入 "quit",line
实际上将是 "quit\n"
,因为 readlines
没有去除换行符。
您可以通过测试 "quit\n"
或对行进行 strip
来解决这个问题。
最后,即使您解决了所有这些问题,您仍然需要永远等待才能执行任何操作。readlines
返回一个行的list
。它唯一可能做到这一点的方式是通过读取将在stdin
上出现的所有行。在读取所有这些行之前,甚至无法开始循环。
当标准输入是文件时,当文件结束时会发生这种情况,因此不是太糟糕。但是当标准输入是Windows命令提示符时,命令提示符永远不会结束。* 因此,这需要很长时间。您无法开始处理行列表,因为等待行列表需要很长时间。
解决方案是不使用
readlines()
。实际上,从任何地方调用
readlines()
都没有好的理由,无论是
stdin
还是其他什么。任何
readlines
可以处理的内容都已经是一个包含行的可迭代对象,就像
readlines
会给你的
list
一样,只不过它是“懒惰”的:它可以一次给你一行,而不是等待并一次性给你所有行。(即使你真的需要列表,也只需执行
list(f)
而不是
f.readlines()
。)
因此,不要使用
for line in sys.stdin.readlines():
,而是使用
for line in sys.stdin:
(或者更好的是,完全替换显式循环并使用迭代器转换序列,如mgilson的答案所示。)
JBernardo、Wing Tang Wong等提出的修复方法都是正确且必要的。之所以他们的方法没有解决您的问题,是因为如果您有4个错误,并修复了一个,您的代码仍然不起作用。这正是为什么“不起作用”在编程中并不是一个有用的衡量标准,您必须调试实际出错的地方,才能知道自己是否在取得进展。
* 我在关于 stdin
永远不会结束的说法上撒了个小谎。如果您键入控制-Z(您可能需要跟随一个回车),那么 stdin
就会结束。但是,如果您的任务是使其在用户键入“quit”时立即退出,那么只有在用户键入“quit”,然后返回、控制-Z、再次返回的情况下,才能被视为成功。
'quit'!= 'quit\n'
。 - JBernardosys.stdin.readlines()
。这会返回一个行的列表。显然,在获取所有行之前,它无法生成该列表,这意味着在关闭标准输入之前它无法返回。解决方法就是……不要调用readlines()
。当然,解决了JBernardo展示的问题后,可能会出现新的问题,但这并不意味着你不需要解决这个问题。 - abarnert