2

我正在尝试实现一种简单的方法,以在每次调用该方法时从日志文件中读取新行。

我查看了关于stackoverflow(例如here)和其他地方模拟“tail”功能的各种建议;大多数涉及使用readline()读取新行,因为它们被附加到文件中。它应该足够简单,但不能让它在带有 Python 2.6.1 的 OS X 10.6.4 上正常工作。

为了解决问题的核心,我尝试了以下方法:

  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. 在第一个 shell 中,将另外两行添加到“test.log”,使其看起来像这样:

    one
    two
    three
    four
    five
    
  5. 回到第二个 shell,执行以下代码:

    >>> 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 进行了同样的尝试,它可以按我的预期工作。我在我的 Mac 上尝试了 2.5,但得到了与 2.6 相同的结果。

我必须在这里遗漏一些基本的东西。有任何想法吗?

4

2 回答 2

3

您如何在文件中再添加两行?

大多数文本编辑器会经历很多这样的操作:

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;几乎每个文本编辑器的 inode 编号都会改变。)

如果您使用 shell 的重定向附加到日志文件>>,它将完全按照应有的方式工作:

$ 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命令行选项来处理文件更改但存在同名文件的情况。(非常适合观看可能会定期轮换的日志文件。)

于 2010-08-14T11:23:29.303 回答
2

简短的回答:不,你的假设是。

您的文本编辑器正在创建一个同名的新文件,而不是修改旧文件。您可以在stat结果中看到st_ino不同。如果你这样做os.fstat(log.fileno()),你会得到旧的尺寸和旧的st_ino

如果您想在 的实现中检查这一点,请定期tail比较st_ino和结果。如果它们不同,则有一个同名的新文件。statfstat

于 2010-08-14T11:26:40.977 回答