OS X上的Python的seek()是否已损坏?

时间:2010-08-14 11:06:22

标签: python macos seek

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

我已经在stackoverflow(例如here)和其他地方查看了各种建议,以模拟“尾部”功能;大多数都涉及使用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()带到了one two three four five 报告的文件末尾,字节14。

  4. 在第一个shell中,将另外两行添加到“test.log”,使其如下所示:

    >>> 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
    >>> 
    
  5. 返回第二个shell,执行以下代码:

    os.stat()
  6. 这里我们从{{1}}看到文件的大小现在是24个字节,但是寻找到文件的末尾仍然指向字节14?我在使用Python 2.5的Ubuntu上尝试过相同的操作,它可以像我期望的那样工作。我在Mac上尝试使用2.5,但得到的结果与2.6相同。

    我必须遗漏一些基本的东西。有什么想法吗?

2 个答案:

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

答案 1 :(得分:2)

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

您的文本编辑器正在创建一个具有相同名称的新文件,而不是修改旧文件。您可以在stat结果中看到st_ino不同。如果您要执行os.fstat(log.fileno()),则会获得旧的st_ino旧版本。

如果您想在tail的实施中检查此问题,请定期比较st_inostat结果的fstat。如果它们不同,则会有一个同名的新文件。