Tee does not show output or write to file
Here's a simpler way of reproducing your issue:
$ cat foo.py
from time import sleep
while True:
sleep(2)
print "hello"
$ python foo.py
hello
hello
(...)
$ python foo.py | tee log
(no output)
This happens because python
buffers stdout when it's not a terminal. The easiest way to unbuffer it is to use python -u
:
$ python -u foo.py | tee log
hello
hello
(...)
You can also set the shebang to #!/usr/bin/python -u
(this does not work with env
).
Related videos on Youtube
Lily Mara
Updated on September 16, 2022Comments
-
Lily Mara over 1 year
I wrote a python script to monitor the statuses of some network resources, an infinite pinger if you will. It pings the same 3 nodes forever until it receives a keyboard interrupt. I tried using tee to redirect the output of the program to a file, but it does not work:
λ sudo ./pingster.py 15:43:33 node1 SUCESS | node2 SUCESS | node3 SUCESS 15:43:35 node1 SUCESS | node2 SUCESS | node3 SUCESS 15:43:36 node1 SUCESS | node2 SUCESS | node3 SUCESS 15:43:37 node1 SUCESS | node2 SUCESS | node3 SUCESS 15:43:38 node1 SUCESS | node2 SUCESS | node3 SUCESS ^CTraceback (most recent call last): File "./pingster.py", line 42, in <module> main() File "./pingster.py", line 39, in main sleep(1) KeyboardInterrupt λ sudo ./pingster.py | tee ping.log # wait a few seconds ^CTraceback (most recent call last): File "./pingster.py", line 42, in <module> main() File "./pingster.py", line 39, in main sleep(1) KeyboardInterrupt λ file ping.log ping.log: empty
I am using colorama for my output, I thought that perhaps could be causing the issue, but I tried printing something before I even imported colorama, and the file is still empty. What am I doing wrong here?
Edit: Here is the python file I'm using
#!/home/nate/py-env/ping/bin/python from __future__ import print_function from datetime import datetime from collections import OrderedDict from time import sleep import ping import colorama def main(): d = { 'node1': '10.0.0.51', 'node2': '10.0.0.50', 'node3': '10.0.0.52', } addresses = OrderedDict(sorted(d.items(), key=lambda t: t[0])) colorama.init() while True: status = [] time = datetime.now().time().strftime('%H:%M:%S') print(time, end='\t') for location, ip_address in addresses.items(): loss, max_time, avg_time = ping.quiet_ping(ip_address, timeout=0.5) if loss < 50: status.append('{0} SUCESS'.format(location)) else: status.append( '{}{} FAIL{}'.format( colorama.Fore.RED, location, colorama.Fore.RESET, ) ) print(' | '.join(status)) sleep(1) if __name__ == '__main__': main()
-
Ar5hv1r almost 8 yearsIf you can't modify the
python
invocation you can set thePYTHONUNBUFFERED
environment variable to a non-empty string and this will have the same effect.man python
describes the behavior in more detail