Python EOF для многобайтовых запросов file.read () - PullRequest
10 голосов
/ 13 декабря 2010

Документы Python по file.read () утверждают, что An empty string is returned when EOF is encountered immediately. В документации также указывается:

Обратите внимание, что этот метод может вызывать лежащая в основе C функция fread () чем один раз в попытке приобрести как как можно ближе к размеру байтов. Также обратите внимание, что в неблокирующем режиме может быть меньше данных, чем было запрошено возвращается, даже если нет параметра размера был дан.

Я полагаю, что Гвидо решил не добавлять f.eof () ИДЕАЛЬНО ОЧИСТИТЬ , поэтому нужно использовать способ Python!

Однако мне неясно, является ли это окончательным тестом, что вы достигли EOF, если вы получили меньше запрошенных байтов из чтения, но вы его получили.

е:

with open(filename,'rb') as f:
    while True:
        s=f.read(size)
        l=len(s) 
        if l==0: 
            break     # it is clear that this is EOF...
        if l<size:
            break      # ? Is receiving less than the request EOF???

Это потенциальная ошибка для break, если вы получили меньше байтов, запрошенных при вызове file.read(size)?

Ответы [ 2 ]

22 голосов
/ 14 декабря 2010

Вы не думаете, что у вас змеиная шкура ... Python - это не C.

Сначала обзор:

  • st = f.read () читает в EOF или, если открыт как двоичный файл, до последнего байта;
  • st = f.read (n) пытается прочитать n байтов и ни в коем случае не более n байтов;
  • st = f.readline () читает строку за раз, строка заканчивается на \ n или EOF;
  • st = f.readlines () использует readline () для чтения всех строк в файле и возвращает список строк.

Если метод чтения файла находится в EOF, он возвращает ''. Такой же тип теста EOF используется в других «файловых» методах, таких как StringIO, socket.makefile и т. Д. Возврат менее чем n байтов из f.read(n), безусловно, НЕ является диспозитивным тестом для EOF! код может работать в 99,99% случаев, это то время, когда он не работает, и найти его очень сложно. Плюс, это плохая форма Python. Единственное использование для n в этом случае - это установить верхний предел размер возврата.

По каким причинам файловые методы Python возвращают меньше , чем n байт?

  1. EOF, безусловно, распространенная причина;
  2. Сетевой сокет может тайм-аут при чтении, но остается открытым;
  3. Точно n байтов может привести к разрыву между логическими многобайтовыми символами (такими как \r\n в текстовом режиме и, я думаю, многобайтовым символом в Unicode) или некоторой базовой структурой данных, которая вам не известна;
  4. Файл находится в неблокирующем режиме, и другой процесс начинает доступ к файлу;
  5. Временное отсутствие доступа к файлу;
  6. Базовое состояние ошибки, потенциально временное, для файла, диска, сети и т. Д.
  7. Программа получила сигнал, но обработчик сигнала проигнорировал его.

Я бы переписал ваш код следующим образом:

with open(filename,'rb') as f:
    while True:
        s=f.read(max_size)
        if not s: break

        # process the data in s...

Или написать генератор :

def blocks(infile, bufsize=1024):
    while True:
        try:
            data=infile.read(bufsize)
            if data:
                yield data
            else:
                break
        except IOError as (errno, strerror):
            print "I/O error({0}): {1}".format(errno, strerror)
            break

f=open('somefile','rb')

for block in blocks(f,2**16):
    # process a block that COULD be up to 65,536 bytes long
1 голос
/ 13 декабря 2010

Вот что написано в документации моего компилятора C для функции fread():

size_t fread( 
   void *buffer,
   size_t size,
   size_t count,
   FILE *stream 
);

Фред возвращает количество полных позиций на самом деле читать, что может быть меньше, чем считать, если произошла ошибка или если конец файла встречается раньше счетчик достижений.

Таким образом, похоже, что значение меньше size означает, что произошла ошибка или достигнут EOF - так что break выход из цикла будет правильным решением.

...