我有以下功能:
def getInput():
# define buffer (list of lines)
buffer = []
run = True
while run:
# loop through each line of user input, adding it to buffer
for line in sys.stdin.readlines():
if line == 'quit\n':
run = False
else:
buffer.append(line.replace('\n',''))
# return list of lines
return buffer
在我的函数takeCommands()中调用,调用它来实际运行我的程序。
然而,这没有做任何事情。我希望将每一行添加到一个数组中,一旦一行=='退出',它就会停止用户输入。我已经尝试了for line in sys.stdin.readlines()
和for line sys.stdin
,但它们都没有注册我的任何输入(我在Windows命令提示符下运行它)。有任何想法吗?感谢
答案 0 :(得分:6)
所以,把你的代码从函数中取出并运行一些测试。
import sys
buffer = []
while run:
line = sys.stdin.readline().rstrip('\n')
if line == 'quit':
run = False
else:
buffer.append(line)
print buffer
的变化:
另一种方式:
import sys
buffer = []
while True:
line = sys.stdin.readline().rstrip('\n')
if line == 'quit':
break
else:
buffer.append(line)
print buffer
取出'run'变量,因为它并不是真的需要。
答案 1 :(得分:1)
我会使用itertools.takewhile
:
import sys
import itertools
print list(itertools.takewhile(lambda x: x.strip() != 'quit', sys.stdin))
另一种方法是使用双参数iter
形式:
print list(iter(raw_input,'quit'))
这样做的好处是raw_input
可以解决所有的行缓冲问题,并且它已经为你删除了换行符 - 但是如果用户忘记添加,它将循环直到内存不足脚本quit
。
这两个都通过了测试:
python test.py <<EOF
foo
bar
baz
quit
cat
dog
cow
EOF
答案 2 :(得分:0)
此代码存在多个单独的问题:
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
不会突破该循环。一旦你输入“退出”,它就会一直停止,直到它看到所有的行,然后然后退出,如果你在任何时候键入“退出”。
您可以在break
之后添加run = False
,轻松解决此问题。
但是,无论有没有修复,如果你没有在第一次通过外循环时输入“quit”,因为你已经读过所有输入,所以没有别的东西可以阅读,所以你将永远地一遍又一遍地运行一个空的内循环,你永远不能退出。
你有一个循环意味着“读取并处理所有输入”。你想要那个一次。那么,外环应该是什么?它不应该是;做一次的方法是不使用循环。所以,要解决这个问题,请摆脱run
和while run:
循环;只需使用内循环。
然后,如果您输入“退出”,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(您可能需要也可能不需要返回它),那么stdin
就完成了。但是,如果你的任务是在用户键入“quit”&lt;转入仅在用户键入“退出”然后返回时退出的内容,control-Z,再次返回可能不会被视为成功。