为了账号安全,请及时绑定邮箱和手机立即绑定

windows下python使用fllow扩展持续读取文件的bug

标签:
Python

一、前言

      python通过fllow读取文件,需求是可以监控log文件,当文件行数增加的话,就写入到数据库,也可以读取历史log文件,写入到数据库,因此我们通过给脚本添加参数的方式来区分是否监控log文件。

      可是当执行python的时候,明明log文件没有新增数据,但是发现每隔60spython就会读取log文件的旧数据,并插入到数据库。这当然是不符合需求的,正常来说,log文件无变化,fllow不应该再去读取文件才对。

二、读取fllow源码

遇到文件就读源码,码中自有黄金屋,码中自有颜如玉。

1、fllow读取文件代码

thefile = follow.Follow(filename, False)

fllow的Follow函数如下:
class Follow(object):
    def __init__(self, fname, start=False, new_file_check=60, *open_args):

可以看到参数中有个new_file_check =60,这个参数会不会就是罪魁祸首呢?

2、跟踪new_file_check 函数

def _preread(self):
        if not self.f:
            self._reopen(False)
            return
        t = time.time()
        if t >= self.stat_time + self.stat_time_min:   # 这部分用到了
            nstat = os.stat(self.fname)
            self.stat_time = t
            if nstat.st_dev != self.stat.st_dev or \
                    nstat.st_ino != self.stat.st_ino:
                # start at top of new file
                self._reopen(True)
                return
        # should clear previous EOF condition
        self.f.seek(self.pos)

代码的语意是:

      当60s之后,脚本会重新获取文件的相关属性,并对比文件的相关参数,若参数不一致则重新读取文件。

看来问题就出在了这个对比属性上,下面先看看这些属性都是什么意思

3、python的stat函数

根据if条件左边的代码格式,我们知道是用os.stat()函数的返回值进行对比的。
根据if条件右边的代码格式,我们可追踪代码,最终锁定在os.fstat()函数

手册解析:

https://www.runoob.com/python/os-stat.html
os.stat() 方法用于在给定的路径上执行一个系统 stat 的调用。

https://www.runoob.com/python/os-fstat.html
os.fstat() 方法用于返回文件描述符fd的状态,类似 stat()Unix,Windows上可用。

根据这个教程,我们发现

os.stat返回的结果有:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。 等

os.fstat返回的结果有:

st_dev: 设备信息
st_ino: 文件的i-node值

4、分析出错代码

if nstat.st_dev != self.stat.st_dev or \
        nstat.st_ino != self.stat.st_ino:
        # start at top of new file
         self._reopen(True)
         return
首先是对比: inode 驻留的设备 != 设备信息
其次是对比:inode 节点号 != 文件的i-node值

      两次对比有一次不同则重新读取文件,也就是造成我们上面的bug

三、windows下对比inode 节点号

1、windows下打印这几个参数

   print nstat.st_dev
   print self.stat.st_dev
   print nstat.st_ino
   print self.stat.st_ino

结果:
0
0
0
73746443898579758

      OK,根据结果已经知道是文件的inode值不同,所以造成了重新读取文件的bug。那么为什么文件属性会发生变化呢,本地数据量又没有增加。而且既然这个文件是常用的读取文件脚本,那么怎么可能会有这明显的bug

2、os.start() 与 os.fstat()

      首先明确一点,两个函数都能在windows下正常运行。函数含义也有些相似,唯一不一样的一点就是inode的值,关于inode,听说最多的就是linux文件系统的inode了,那么会不会是windows下的inodelinuxinode不一样,或者windows不够稳定呢

3、linux文件的inode会保持不变吗?

答案:
      inode在文件的生命周期里是不改变的,除非,你把文件删除重建。而你删除文件前100行的动作,实际上是新建一个临时文件,把旧文件第100行以后的东西输出到临时文件里,删掉旧文件,把临时文件的文件名重命名成旧文件的名字。也就是说你删前100行的时候,文件已经经历了删除-重建的过程,inode号也就改变了。

作者:北极
链接:https://www.zhihu.com/question/26127845/answer/32214159
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

4、windows文件的inode会保持不变吗?

      通过搜索我们发现,对于windows来说,它有类似于inode的概念,比如通过卷序列号/ FileId组合等来标识目录文件,但是windows下并没有直接的inode概念,所以在windows下通过inode对比文件是不稳定且不精准的。

      这样一对比,答案就很明显了,windows下问题奇葩问题多,怪不得大佬们都用mac电脑开发呢,大佬们果然诚不我欺。

四、解决方案

      通过以上的分析,可以知道这个锅算是windows的锅,怪不得py脚本在windows下那么多的bug,因为windowslinux在某些函数调用上还是有一些差距的,建议是到linux服务器上跑一跑看看。

      因此上传py脚本到linux,在linux上测试,发现完美实现监控日志文件的目的,文件有更新则写入到数据库,无更新则持续读取。

五、总结

      通过这篇文章的分析,对博主对打的触动就是:windows环境果然是坑。 怪不得大佬们都是用mac电脑,天天在linux下开发呢,博主本来在windows下开发php开发的不亦乐乎,只可惜以后始终是要用到编译型语言的,早晚都要完全在linux下开发啊。。

      行吧,解决问题的过程永远是复杂的,查找的过程永远是享受,通过这个问题博主又学到了很多python的知识,整体来说还是很赞的。

我是铁柱,我为自己代言!

end

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消