Python面试题解析丨Python实现tail -f功能
文件指针定位之 seek 方法
seek(offset, from)
offset :文件指针偏移量(很多博客在这里将offset定义为指针偏移量,但是目前我的看法是这里定义为指针的相对位置)
from : 0-文件开头 1-当前位置 2-文件末尾(这里的0,1,2只是代表了文件位置
代码示例
file_name = "new2.txt"
fp = open(file_name, "r",encoding='utf8')
print("当前文件指针位置 : ", fp.tell())
str = fp.read(18)
print("fp.read(18)读取到的数据 : ", str)
print("当前文件位置 : ", fp.tell())
fp.seek(9,0) # 见说明3
print("fp.seek(9,0),当前文件指针位置 : ", fp.tell())
str=fp.readline()
print("fp.readline()读取到的数据 : ", str)
print("当前文件指针位置 : ", fp.tell())
实战例子通过python实现Linux tail 功能
with open('test.txt') as f:f.seek(0,2)while True:last_pos = f.tell()line = f.readline() if line:print line
优化版1
# coding=utf-8
import sys
import timedef readCase(filePath):file = open(filePath, 'r', encoding='UTF-8')content = file.readlines()# print(content)file.close()return contentdef readCase2(filePath):with open(filePath, 'r', encoding='UTF-8') as file:content = file.readlines()return contentclass Tail():def __init__(self,file_name,callback=sys.stdout.write):self.file_name = file_nameself.callback = callbackdef follow(self):try:with open(self.file_name, 'r', encoding='UTF-8') as f:f.seek(0,2) while True:line = f.readline() if line:self.callback(line)time.sleep(1)except :print('打开文件失败,囧,看看文件是不是不存在,或者权限有问题')
#
#
# 使用默认的sys.stdout.write打印到屏幕
py_tail = Tail('new2.txt')
py_tail.follow()
# ans = readCase2('new2.txt')
# print(ans)
# # 自己定义处理函数
# def test_tail(line):
# print( 'xx'+line+'xx')
#
# py_tail1 = Tail('new2.txt', test_tail)
# py_tail1.follow()
优化版2 输出末尾10行
import sys
import timeclass Tail():def __init__(self,file_name,callback=sys.stdout.write):self.file_name = file_nameself.callback = callbackdef follow(self,n=10):try:with open(self.file_name, 'r', encoding='UTF-8') as f:self.showLastLine(f,n)f.seek(0,2)while True:line = f.readline()if line:self.callback(line)except:print('打开文件失败,囧,看看文件是不是不存在,或者权限有问题')def showLastLine(self,f, n):# print(f.readlines())last_lines = f.readlines()[-n:]for line in last_lines:self.callback(line)# 使用默认的sys.stdout.write打印到屏幕
py_tail = Tail('new2.txt')
py_tail.follow()
优化3
# coding=utf-8
import sys
import timeclass Tail():def __init__(self,file_name,callback=sys.stdout.write):self.file_name = file_nameself.callback = callbackdef follow(self,n=10):try:# 打开文件with open(self.file_name) as f:self._file = fself._file.seek(0,2)# 存储文件的字符长度self.file_length = self._file.tell()# 打印最后10行self.showLastLine(n)# 持续读文件 打印增量while True:line = self._file.readline()if line:self.callback(line)time.sleep(1)except:print('打开文件失败,囧,看看文件是不是不存在,或者权限有问题')def showLastLine(self, n):# 一行大概100个吧 这个数改成1或者1000都行len_line = 100# n默认是10,也可以follow的参数传进来read_len = len_line*n# 用last_lines存储最后要处理的内容while True:# 如果要读取的1000个字符,大于之前存储的文件长度# 读完文件,直接breakif read_len>self.file_length:self._file.seek(0)last_lines = self._file.read().split('\n')[-n:]break# 先读1000个 然后判断1000个字符里换行符的数量self._file.seek(-read_len, 2)last_words = self._file.read(read_len)# count是换行符的数量count = last_words.count('\n')if count>=n:# 换行符数量大于10 很好处理,直接读取last_lines = last_words.split('\n')[-n:]break# 换行符不够10个else:# break#不够十行# 如果一个换行符也没有,那么我们就认为一行大概是100个if count==0:len_perline = read_len# 如果有4个换行符,我们认为每行大概有250个字符else:len_perline = read_len/count# 要读取的长度变为2500,继续重新判断read_len = len_perline * nfor line in last_lines:self.callback(line+'\n')if __name__ == '__main__':py_tail = Tail('test.txt')py_tail.follow(20)