2010-08-14 49 views
2

我试图实现一个简单的方法,每次调用该方法时从日志文件中读取新行。OS X上的Python 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()字节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 ??我已经在Python 2.5上用Python 2.5尝试过,它的工作方式与我的预期相同。我在我的Mac上试用了2.5,但获得了与2.6相同的结果。

我必须缺少的东西在这里根本。有任何想法吗?

+0

如果使用os.SEEK_END而不是文字2,会得到不同的结果吗? – Macha 2010-08-14 11:11:22

+0

马查 - 没有区别。问题是我的测试场景... – 2010-08-14 12:05:00

回答

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检查它;索引节点号将用于几乎所有的文本编辑器修改。)

如果使用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命令行选项来处理文件被更改的情况,但存在一个具有相同名称的文件。 (非常适合观看可能会周期性旋转的日志文件。)

+0

我完全错过了 - 非常感谢您的澄清! – 2010-08-14 11:58:15

2

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

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

如果您想在执行tail时检查此项,请定期比较statfstat结果中的st_ino。如果它们不同,则会有一个具有相同名称的新文件。

+0

是的,我错过了文件被重新创建。谢谢! – 2010-08-14 11:59:05