實現Linux tail -f功能
阿新 • • 發佈:2019-02-20
迴圈
這個比較好像,不停的去讀檔案,讀到就打印出來
f = open('a','r')
print(f.read(),end='')
while True:
try:
print(f.read(),end='')
except KeyboardInterrupt:
f.close()
break
CPU佔用100%,不是一個好的選擇。
select、poll
一直以來,對select和poll的用法侷限於套接字,實際上,只要是檔案描述符,都可以監控。
select
import select
f = open('a' ,'r')
while True:
try:
rs, ws, es = select.select([f, ], [], [])
for i in rs:
buf = i.read()
print(buf, end='')
except KeyboardInterrupt:
f.close()
break
poll
import select
f = open('a','r')
poller = select.poll()
fd_to_file = {}
poller.register(f,select.POLLIN)
while True:
try:
events = poller.poll()
for fd,flag in events:
if flag and fd == f.fileno():
print(f.read(),end='')
except KeyboardInterrupt:
f.close()
break
然而,CPU佔用率還是100%,原因由於作為一個普通檔案描述符,時刻準備著讀寫事件,這使得select、poll不會阻塞,自然相當於是死迴圈。
此外,epoll不支援監控普通檔案描述符
inotify
Inotify 是一個 Linux特性,它監控檔案系統操作,比如讀取、寫入和建立。Inotify 反應靈敏,用法非常簡單,並且比 cron 任務的繁忙輪詢高效得多。
tail -f實際上就是inotify+select實現的,Python上一個封裝的比較好的庫pyinotify
使用的是inotify+epoll,效率自然不低。
# coding=utf-8
import pyinotify
class EventHandler(pyinotify.ProcessEvent):
"""事件處理"""
def my_init(self, **kargs):
self.fd = kargs['fd']
def process_IN_MODIFY(self, event):
print(self.fd.read(), end='')
path = './a'
f = open(path,'r')
wm = pyinotify.WatchManager()
mask = pyinotify.IN_MODIFY
notifier = pyinotify.Notifier(wm,EventHandler(fd=f))
wm.add_watch(path,mask,auto_add=True,rec=True)
print('now starting monitor %s' % path)
print(f.read(),end='')
while True:
try:
notifier.process_events()
if notifier.check_events():
notifier.read_events()
except KeyboardInterrupt:
notifier.stop()
break
幾乎看不到CPU佔用,屬上乘。