Итератор файла Python по двоичному файлу с более новой идиомой

В Python для двоичного файла я могу написать следующее:

buf_size=1024*64 # this is an important size... with open(file, "rb") as f: while True: data=f.read(buf_size) if not data: break # deal with the data.... 

С текстовым файлом, который я хочу читать по очереди, я могу написать следующее:

  • Что значит «потреблять» в Python? В итераторе?
  • Итерации по всем парам последовательных элементов из данного списка
  • поведение python groupby?
  • Как zip (* * n) работает в Python?
  • python произвольно увеличивает итератор внутри цикла
  • izip_longest в itertools: Как работает индексирование IndexError внутри итератора?
  •  with open(file, "r") as file: for line in file: # deal with each line.... 

    Это сокращенно:

     with open(file, "r") as file: for line in iter(file.readline, ""): # deal with each line.... 

    Эта идиома зарегистрирована в PEP 234, но мне не удалось найти аналогичную идиому для двоичных файлов.

    Я пробовал это:

     >>> with open('dups.txt','rb') as f: ... for chunk in iter(f.read,''): ... i+=1 >>> i 1 # 30 MB file, i==1 means read in one go... 

    Я попытался положить iter(f.read(buf_size),'') но это синтаксическая ошибка из-за паренс после вызываемого в iter ().

    Я знаю, что могу написать функцию, но есть ли способ с идиомой по умолчанию for chunk in file: где я могу использовать размер буфера по сравнению с ориентированной линией?

    Спасибо, что поделился с новичком Python, который пытался написать свой первый нетривиальный и идиоматический скрипт Python.

  • Создайте базовый итератор Python
  • Как перебирать строки в двух файлах одновременно?
  • Самый эффективный способ поиска последних x строк файла в python
  • Использование MultipartPostHandler для данных формы POST с помощью Python
  • Python: конвертировать итерацию в поток?
  • Объект 'numpy.float64' не повторяется
  • 2 Solutions collect form web for “Итератор файла Python по двоичному файлу с более новой идиомой”

    Я не знаю какого-либо встроенного способа сделать это, но функцию обертки достаточно легко написать:

     def read_in_chunks(infile, chunk_size=1024*64): while True: chunk = infile.read(chunk_size) if chunk: yield chunk else: # The chunk was empty, which means we're at the end # of the file return 

    Затем в интерактивном приглашении:

     >>> from chunks import read_in_chunks >>> infile = open('quicklisp.lisp') >>> for chunk in read_in_chunks(infile): ... print chunk ... <contents of quicklisp.lisp in chunks> 

    Конечно, вы можете легко адаптировать это для использования с блоком:

     with open('quicklisp.lisp') as infile: for chunk in read_in_chunks(infile): print chunk 

    И вы можете исключить инструкцию if.

     def read_in_chunks(infile, chunk_size=1024*64): chunk = infile.read(chunk_size) while chunk: yield chunk chunk = infile.read(chunk_size) 

    Пытаться:

     >>> with open('dups.txt','rb') as f: ... for chunk in iter((lambda:f.read(how_many_bytes_you_want_each_time)),''): ... i+=1 

    iter нуждается в функции с нулевыми аргументами.

    • простой f.read будет читать весь файл, так как параметр size отсутствует;
    • f.read(1024) означает вызов функции и передачу ее возвращаемого значения (данные, загруженные из файла) на iter , поэтому iter не получает никакой функции;
    • (lambda:f.read(1234)) – это функция, которая принимает нулевые аргументы (ничего между lambda и f.read(1234) и вызывает f.read(1234) .

    Существует эквивалентность между следующими:

     somefunction = (lambda:f.read(how_many_bytes_you_want_each_time)) 

    а также

     def somefunction(): return f.read(how_many_bytes_you_want_each_time) 

    и имея один из них перед вашим кодом, вы можете просто написать: iter(somefunction, '') .

    Технически вы можете пропустить круглые скобки вокруг лямбда, грамматика питона примет это.

    Python - лучший язык программирования в мире.