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() で呼び出されます。

ただし、これは何もしません。各行を配列に追加したいと思っています。一度行 == 'quit' すると、ユーザー入力の取得が停止します。for line in sys.stdin.readlines()と の両方を試しまし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」ループを削除しました
  • 「readlines」の代わりに「readline」を使用する
  • 入力後の '\n' を取り除くと、その後のすべての処理がはるかに簡単になります。

別の方法:

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

実際には必要ないので、'run' 変数を取り出します。

于 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、既に改行が削除されますが、ユーザーがquitスクリプトに a を追加するのを忘れた場合、メモリが不足するまでループします。

これらは両方ともテストに合格します。

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」と入力すると終了します。

breakの後にを追加することで、これを簡単に修正できますrun = False


しかし、その修正の有無にかかわらず、最初の外側のループで「quit」と入力しなかった場合は、すべての入力を既に読み取っているため、他に読み取るものがないため、空のコマンドを実行し続けるだけです。内部ループを永遠に繰り返し、決して抜け出すことはできません。

「すべての入力を読み取って処理する」ことを意味するループがあります。あなたはそれを一度だけしたいと思っています。では、外側のループはどうあるべきでしょうか? とにかくそうであってはなりません。一度何かを行う方法は、ループを使用しないことです。runしたがって、これを修正するには、while run:ループを取り除きます。内側のループを使用するだけです。


次に、「quit」と入力すると、改行が削除されないため、line実際には になります。"quit\n"readlines

"quit\n"をテストするかstrip、回線に pingを実行して、これを修正します。


最後に、これらの問題をすべて解決したとしても、何もする前に永遠に待つ必要があります。readlines行の a を返しますlist。これを実行できる唯一の方法は、今後オンになるすべての行を読み取ることですstdin。これらの行をすべて読むまで、ループを開始することさえできません。

標準入力がファイルの場合、それはファイルの終了時に発生するので、それほどひどいものではありません。しかし、標準入力が Windows のコマンド プロンプトの場合、コマンド プロンプトは決して終了しません。* したがって、これには永遠に時間がかかります。行のリストを待つのに永遠にかかるため、行のリストの処理を開始することはできません。

解決策は、使用しないことreadlines()です。readlines()本当に、何かを呼び出すかどうかにかかわらず、正当な理由はありstdinません。readlines動作するものはすべて、それが与えるのと同じように、すでに行でいっぱいのイテラブルです。ただし、それは「怠惰」であることを除いて: 一度にすべての行を待って与えるのではなく、一度に 1 行ずつ与えることができます。(そして、本当にリストが必要な場合でも、代わりに実行してください。)listreadlineslist(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」と入力するとすぐに終了するようにする場合 < ユーザーが「quit」と入力してから戻るときにのみ終了するものを入れる場合、control-Z、return はおそらく成功したとは見なされません。

于 2013-03-28T22:41:01.197 に答える