12
4

3 に答える 3

8

例外は Python からではなく、パイプのシークを許可しないオペレーティング システムから発生します。(通常のパイプからの出力をリダイレクトすると、標準入力であってもシークできます。)これが、クラスが同じであっても、あるケースではエラーが発生し、別のケースではエラーが発生しない理由です。

先読みのための従来の Python 2 ソリューションは、先読みを実装する独自のストリーム実装でストリームをラップすることです。

class Peeker(object):
    def __init__(self, fileobj):
        self.fileobj = fileobj
        self.buf = cStringIO.StringIO()

    def _append_to_buf(self, contents):
        oldpos = self.buf.tell()
        self.buf.seek(0, os.SEEK_END)
        self.buf.write(contents)
        self.buf.seek(oldpos)

    def peek(self, size):
        contents = self.fileobj.read(size)
        self._append_to_buf(contents)
        return contents

    def read(self, size=None):
        if size is None:
            return self.buf.read() + self.fileobj.read()
        contents = self.buf.read(size)
        if len(contents) < size:
            contents += self.fileobj.read(size - len(contents))
        return contents

    def readline(self):
        line = self.buf.readline()
        if not line.endswith('\n'):
            line += self.fileobj.readline()
        return line

sys.stdin = Peeker(sys.stdin)

sys.stdinデコードされていないストリームをピークしながら完全にサポートする Python 3 では、複雑です。stdin.buffer上記のようにラップし、ピーク可能なTextIOWrapperストリームに対して新しいインスタンスを作成し、それをTextIOWrapperとしてインストールしsys.stdinます。

ただし、 をのぞくだけでよいのでsys.stdin.buffer、上記のコードは と に変更した後でも問題なく動作cStringIO.StringIOします。io.BytesIO'\n'b'\n'

于 2013-01-12T11:26:57.177 に答える
3

user4815162342 のソリューションは非常に便利ですが、io.BufferedReader peek メソッドの現在の動作とは異なるという問題があるようです。

組み込みメソッドは、順次 peek() 呼び出しに対して同じデータを (現在の読み取り位置から開始して) 返します。

user4815162342 のソリューションは、シーケンシャル ピーク コールごとにデータのシーケンシャル チャンクを返します。これは、ユーザーが同じデータを複数回使用したい場合、peek を再度ラップして出力を連結する必要があることを意味します。

組み込みの動作を返すための修正は次のとおりです。

def _buffered(self):
    oldpos = self.buf.tell()
    data = self.buf.read()
    self.buf.seek(oldpos)
    return data

def peek(self, size):
    buf = self._buffered()[:size]
    if len(buf) < size:
        contents = self.fileobj.read(size - len(buf))
        self._append_to_buf(contents)
        return self._buffered()
    return buf

フルバージョンはこちら

適用できる他の最適化があります。たとえば、バッファを使い果たす読み取り呼び出しで以前にバッファリングされたデータを削除します。現在の実装では、ピークされたデータはバッファに残りますが、そのデータにはアクセスできません。

于 2017-04-27T10:41:25.033 に答える