Использование io.BufferedReader для потока, полученного с помощью open()?
Я хочу использовать буферизованный поток, потому что хочу использовать метод peek()
, чтобы заглядывать вперед, но использовать мой поток с другим методом, который ожидает файл-подобный объект. (Я бы использовал seek()
, но, возможно, придется обрабатывать сквозные вводы ввода-вывода, которые не поддерживают произвольный доступ.)
Но этот тестовый пример не выполняется:
AttributeError: объект 'file' не имеет атрибута '_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()
не возвращает что-то совместимое с ней?
Ответы
Ответ 1
По внешнему виду вашего оператора print
вы используете Python 2. В этой версии file
не является допустимым аргументом для конструктора BufferedReader
:
В Python 2.x это предлагается как альтернатива встроенному объекту file
, но в Python 3.x это интерфейс по умолчанию для доступа к файлам и потокам. (1)
Вместо этого следует использовать io.open
:
>>> f = io.open(".bashrc", "rb")
Если вы это сделаете, нет необходимости явно переносить его в BufferedReader
, так как именно то, что io.open
возвращает по умолчанию:
>>> type(f)
<type '_io.BufferedReader'>
Подробнее см. его документы; существует аргумент buffering
, который управляет буферизацией.
В Python 3, open is io.open
, поэтому две библиотеки ввода-вывода были объединены в один. Кажется, что io
был добавлен в Python 2.6 в основном для передовой совместимости.
Ответ 2
Вы можете установить количество буферизации в байтах, передав buffering
аргумент, чтобы открыть:
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
- строка буферизирована.
Ответ 3
В 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)