web-dev-qa-db-ja.com

open()で取得したストリームでio.BufferedReaderを使用していますか?

peek()メソッドを使用して先読みするため、バッファリングされたストリームを使用したいが、ファイルのようなオブジェクトを期待する別のメソッドでストリームを使用したい。 (seek()を使用しますが、ランダムアクセスをサポートしていないパイプインI/Oを処理する必要がある場合があります。)

しかし、このテストケースは失敗します。

AttributeError: 'file' object has no attribute '_checkReadable'

_import sys
import io

srcfile = sys.argv[1]
with open(srcfile, 'rb') as f:
    fbuf = io.BufferedReader(f)
    print fbuf.read(20)
_

何が起こっているのですか、どうすれば修正できますか? BufferedReaderはストリームをバッファリングするためのものだと思いました。もしそうなら、なぜopen()関数はそれと互換性のあるものを返さないのですか?

14
Jason S

printステートメントの外観から、Python 2.を使用しています。そのバージョンでは、fileBufferedReaderコンストラクタ:

Python 2.xでは、これは組み込みのfileオブジェクトの代替として提案されていますが、Python 3.xではファイルとストリームにアクセスするためのデフォルトのインターフェースです( 1

代わりにio.openを使用してください:

>>> f = io.open(".bashrc", "rb")

これを行う場合、io.openがデフォルトで正確に返すものであるため、BufferedReaderで明示的にラップする必要はありません。

>>> type(f)
<type '_io.BufferedReader'>

詳細は its docs を参照してください。バッファリングを制御するbuffering引数があります。

Python 3、open is io.openでは、2つのI/Oライブラリが1つにマージされています。ioがPython 2.6主に上位互換性のため。

19
Fred Foo

buffering argument を渡して、バッファリングの量をバイト単位で設定できます。

import sys

srcfile = sys.argv[1]
with open(srcfile, 'rb', buffering=30) as f:
    print(f.peek(30))
    print(f.read(20))

これはBufferedReaderです:

>>> with open("test.txt", 'rb', buffering=30) as f:
...     type(f)
<class '_io.BufferedReader'>

デフォルトでは、バッファリングされて1-バッファリングされた行。

2
Gareth Latty

Python2では、fileによって返されたopenオブジェクトを使用する必要がある場合(または、たとえば変更できないモジュールルーチンによって提供される場合)、fileno()によって取得されたファイル記述子を使用できます。ために io.FileIOコンストラクター、次にio.FileIOオブジェクトからio.BufferedReaderコンストラクタ。

したがって、サンプルコードは次のように書き換えることができます。

import sys
import io

srcfile = sys.argv[1]
with open(srcfile, 'rb') as f:
    fio  = io.FileIO(f.fileno())
    fbuf = io.BufferedReader(fio)
    print fbuf.read(20)
1
majkelx