5

我有以下功能:

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() 中调用它,调用它来实际运行我的程序。

但是,这没有任何作用。我希望将每一行添加到一个数组中,一旦 line == 'quit' 它停止接受用户输入。我都试过了for line in sys.stdin.readlines()and for line sys.stdin,但它们都没有注册我的任何输入(我在 Windows 命令提示符中运行它)。有任何想法吗?谢谢

4

3 回答 3

6

因此,将您的代码从函数中取出并运行一些测试。

import sys
buffer = []
while run:
    line = sys.stdin.readline().rstrip('\n')
    if line == 'quit':
        run = False
    else:
        buffer.append(line)

print buffer

变化:

  • 删除了“for”循环
  • 使用“readline”而不是“readlines”
  • 输入后去掉'\n',因此之后的所有处理都容易得多。

其他方式:

import sys
buffer = []
while True:
    line = sys.stdin.readline().rstrip('\n')
    if line == 'quit':
        break
    else:
        buffer.append(line)
print buffer

取出“运行”变量,因为它并不是真正需要的。

于 2013-03-28T22:00:09.743 回答
3

我会用itertools.takewhile这个:

import sys
import itertools
print list(itertools.takewhile(lambda x: x.strip() != 'quit', sys.stdin))

另一种方法是使用 2 参数iter形式:

print list(iter(raw_input,'quit'))

这样做的好处是raw_input可以处理所有的行缓冲问题,并且它已经为您去除换行符——但是如果用户忘记将 a 添加quit到脚本中,它将循环直到内存不足。

这两个都通过了测试:

python test.py <<EOF
foo
bar
baz
quit
cat
dog
cow
EOF
于 2013-03-28T21:08:28.830 回答
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不会跳出那个循环。它不会在您键入“quit”后立即退出,而是会继续运行,直到查看完所有行,然后在您在任何时候键入“quit”时退出。

您可以通过breakrun = False.


但是,不管有没有这个修复,如果你在第一次通过外循环时没有输入“quit”,因为你已经阅读了所有的输入,没有其他东西可以阅读,所以你只会继续运行一个空的内循环一遍又一遍,你永远无法退出。

您有一个循环,意思是“读取并处理所有输入”。你想只做一次。那么,外循环应该是什么?无论如何都不应该;做某事的方法是不使用循环。run所以,要解决这个问题,摆脱while run:循环;只需使用内部循环。


然后,如果您键入“quit”,line实际上将是"quit\n",因为readlines不会删除换行符。

您可以通过测试"quit\n"stripping 行来修复此问题。


最后,即使你解决了所有这些问题,在做任何事情之前你仍然会永远等待。readlines返回list一行。它可能做到这一点的唯一方法是读取所有将出现的行stdin。在阅读完所有这些行之前,您甚至无法开始循环。

当标准输入是一个文件时,文件结束时会发生这种情况,所以这并不算糟糕。但是当标准输入是 Windows 命令提示符时,命令提示符永远不会结束。*因此,这需要永远。您不必开始处理行列表,因为等待行列表需要很长时间。

解决方案是不使用readlines(). 真的,从来没有一个很好的理由来呼吁或不呼吁readlines()任何事情。stdin任何可以readlines工作的东西都已经是一个充满线条的可迭代对象,就像给你的那样listreadlines除了它是“懒惰的”:它可以一次给你一个线条,而不是等待并一次给你所有线条。(即使你真的需要这个列表,也可以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,再次返回可能不会被认为是成功的。

于 2013-03-28T22:41:01.197 回答