使用sys.stdin获取多行输入

时间:2013-03-28 21:05:45

标签: python sys

我有以下功能:

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命令提示符下运行它)。有任何想法吗?感谢

3 个答案:

答案 0 :(得分: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

取出'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”,因为你已经读过所有输入,所以没有别的东西可以阅读,所以你将永远地一遍又一遍地运行一个空的内循环,你永远不能退出。

你有一个循环意味着“读取并处理所有输入”。你想要那个一次。那么,外环应该是什么?它不应该是;做一次的方法是不使用循环。所以,要解决这个问题,请摆脱runwhile run:循环;只需使用内循环。


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

您可以通过测试"quit\n"strip ping这些行来修复此问题。


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

当标准输入是文件时,会在文件结束时发生,因此 太糟糕了。但是当标准输入是Windows命令提示符时,命令提示符永远不会结束。*所以,这需要永远。您无法开始处理行列表,因为等待行列表需要永远。

解决方案是不使用readlines()。实际上,从来没有充分的理由在readlines()或其他任何地方致电stdinreadlines处理的任何内容已经一个可迭代的行,就像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,再次返回可能不会被视为成功。