Python's seek () на OS X не работает? - PullRequest
2 голосов
/ 14 августа 2010

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

Я рассмотрел различные предложения как по стеку (например, здесь ), так и в других местах для имитации "хвостовой" функциональности; большинство из них включают использование 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.

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

Ответы [ 2 ]

3 голосов
/ 14 августа 2010

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

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

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 для обработки случая, когда файл изменяется, но существует файл с таким же именем. (Отлично подходит для просмотра файлов журнала, которые могут периодически вращаться.)

2 голосов
/ 14 августа 2010

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

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

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

...