Является ли поиск Python () в OS X сломанным?

Я пытаюсь реализовать простой метод для чтения новых строк из файла журнала при каждом вызове метода.

Я просмотрел различные предложения как в stackoverflow (например, здесь) и в других местах для имитации «хвостовой» функциональности; в большинстве случаев используется readline() для чтения новых строк по мере их добавления к файлу. Это должно быть достаточно просто, но не может заставить его работать должным образом в OS X 10.6.4 с включенным Python 2.6.1.

Чтобы добраться до сути проблемы, я попробовал следующее:

  1. Откройте два окна терминала.

  2. В одном создайте текстовый файл «test.log» с тремя строками:

    one
    two
    three
    
  3. В другом запустите python и выполните следующий код:

    Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) 
    [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> os.stat('test.log')
    posix.stat_result(st_mode=33188, st_ino=23465217, st_dev=234881025L, st_nlink=1, st_uid=666, st_gid=20, st_size=14, st_atime=1281782739, st_mtime=1281782738, st_ctime=1281782738)
    >>> log = open('test.log')
    >>> log.tell()
    0
    >>> log.seek(0,2)
    >>> log.tell()
    14
    >>> 
    

    Итак, с помощью tell() мы видим, что seek(0,2) привело нас к концу файла, о чем сообщает os.stat(), байт 14.

  4. В первой оболочке добавьте еще две строки в «test.log», чтобы он выглядел так:

    one
    two
    three
    four
    five
    
  5. Вернитесь ко второй оболочке и выполните следующий код:

    >>> os.stat('test.log')
    posix.stat_result(st_mode=33188, st_ino=23465260, st_dev=234881025L, st_nlink=1, st_uid=666, st_gid=20, st_size=24, st_atime=1281783089, st_mtime=1281783088, st_ctime=1281783088)
    >>> log.seek(0,2)
    >>> log.tell()
    14
    >>> 
    

Здесь мы видим из os.stat(), что размер файла теперь 24 байта, но поиск в конец файла каким-то образом все еще указывает на 14 байт?? Я пробовал то же самое на Ubuntu с Python 2.5, и он работает так, как я ожидаю. Я пробовал с 2.5 на своем Mac, но получил те же результаты, что и с 2.6.

Я должен упустить что-то фундаментальное здесь. Любые идеи?


person Will Harris    schedule 14.08.2010    source источник
comment
Получаете ли вы другой результат, если используете os.SEEK_END вместо литерала 2?   -  person Macha    schedule 14.08.2010
comment
Маша - без разницы. Проблема в моем тестовом сценарии...   -  person Will Harris    schedule 14.08.2010


Ответы (2)


Как вы добавляете еще две строки в файл?

Большинство текстовых редакторов выполняют примерно такие операции:

fd = open(filename, read)
file_data = read(fd)
close(fd)
/* you edit your file, and save it */
unlink(filename)
fd = open(filename, write, create)
write(fd, file_data)

Файл другой. (Проверьте это с помощью ls -li; номер индекса изменится почти для каждого текстового редактора.)

Если вы дополните файл журнала, используя перенаправление >> вашей оболочки, он будет работать точно так, как должен:

$ echo one >> test.log
$ echo two >> test.log
$ echo three >> test.log
$ ls -li test.log
671147 -rw-r--r-- 1 sarnold sarnold 14 2010-08-14 04:15 test.log
$ echo four >> test.log
$ ls -li test.log
671147 -rw-r--r-- 1 sarnold sarnold 19 2010-08-14 04:15 test.log

>>> log=open('test.log')
>>> log.tell()
0
>>> log.seek(0,2)
>>> log.tell()
19

$ echo five >> test.log
$ echo six >> test.log

>>> log.seek(0,2)
>>> log.tell()
28

Обратите внимание, что команда tail(1) имеет параметр командной строки -F для обработки случая, когда файл изменен, но существует файл с таким же именем. (Отлично подходит для просмотра файлов журналов, которые могут периодически меняться.)

person sarnold    schedule 14.08.2010

Краткий ответ: нет, ваши предположения таковы.

Ваш текстовый редактор создает новый файл с тем же именем, не изменяя старый файл на месте. Вы можете видеть в своем результате stat, что st_ino отличается. Если бы вы сделали os.fstat(log.fileno()), вы бы получили старый размер и старый st_ino.

Если вы хотите проверить это в своей реализации tail, периодически сравнивайте st_ino результатов stat и fstat. Если они отличаются, есть новый файл с таким же именем.

person habnabit    schedule 14.08.2010
comment
Да, я пропустил, что файл был воссоздан. Спасибо! - person Will Harris; 14.08.2010