Tailing in Python
Writing complicated systems is a fantastic feeling. You know, ideas so vast that you have to sit down with pen and paper
just to think for a bit. You might even talk with a coworker instead of just imagining your solution is perfect right off the
bat and implementing code_that_wont_get_used_for_various_reasons/misguided_solution.py.r9999
.
Then there are other days. When you have lost the ability to function in any meaningful way and you end up putting a
disproportionate amount of mental energy into crafting a Python version of.. I don't know.. tail
.
If you too are staring at a blank wall in confusion on this fine Sunday, perhaps you can write your own Python implementation
of tail
which meets these requirements:
- supports following newly appended lines to a file (without showing the existing lines of the file),
- supports iterating through all the existing lines and then following new lines as they appear.
Judging criteria are:
- correctness (working is better than not working)
- simplicity (simple is better than complex)
- conciseness (short is better than long)
- performance (fast is better than slow)
- style (mine is better than yours)
Well, get coding!
My Implementation
For your consideration, here is my solution.
import time
from optparse import OptionParser
SLEEP_INTERVAL = 1.0
def readlines_then_tail(fin):
"Iterate through lines and then tail for further lines."
while True:
line = fin.readline()
if line:
yield line
else:
tail(fin)
def tail(fin):
"Listen for new lines added to file."
while True:
where = fin.tell()
line = fin.readline()
if not line:
time.sleep(SLEEP_INTERVAL)
fin.seek(where)
else:
yield line
def main():
p = OptionParser("usage: tail.py file")
(options, args) = p.parse_args()
if len(args) < 1:
p.error("must specify a file to watch")
with open(args[0], 'r') as fin:
for line in readlines_then_tail(fin):
print line.strip()
if name == 'main':
main()
Now, where's yours?