0

I have my python script with many print statements in it. It does some job that takes more than a day, so I need to track log in the output file periodically while it is being executed. if I execute

python migrate.py > output.txt

my file gets populated only after the script is finished (after 24 hours) which doesn't suite me. I tried as well with:

python migrate.py  2>&1 | tee output.txt

But in this case:

  • nothing gets printed in the terminal while this is being executed
  • tail command provides no output until script finishes...

I want to be able to see with tail content of my output file but the size of the file is always 0 until the script is finished. Thanks a lot!

Edit: example of my code (if this is relevant, but I do not think so)

............
.............
.............
def main():
    """
    Script main function
    """
    start_time = datetime.datetime.now()
    print ("----------------------------------------------------------------------------")
    print ("### script started ###")
    args = get_args()
    print ("depot:"+depot)
    print ("stream:"+args[0])
    print ("destination:"+args[1])

    print ("----------------------------------------------------------------------------")
    
    logfile = get_history(args[0])
    print ("----------------------------------------------------------------------------")
    
    git_migrate(logfile, args[0], args[1], args[2], args[3], depot)
    print ("----------------------------------------------------------------------------")        

        
    print ("### script completed ###")    
    end_time = datetime.datetime.now()
    print('Duration: {}'.format(end_time - start_time))


if __name__ == '__main__':
    main()
vel
  • 1,000
  • 1
  • 13
  • 35
  • Try writing to file using Python f.write instead of bash redirect – matszwecja Apr 04 '22 at 10:01
  • @matszwecja can you please give example? thx – vel Apr 04 '22 at 10:02
  • Could You Tell What Exactly Like Somewhat The File Is Doing? For Example If Its Like A While Loop Or Something, then you can initiate a variable having the time when it started. Then In The While Loop you can check the time again and if the difference is lets say a multiple of one hour then return the state of the variables which are being used in that program or whatever you need and then write it to a file. – mrtechtroid Apr 04 '22 at 10:05
  • output file just contains all the prints from `print` statements in it... I do not understand what you are asking – vel Apr 04 '22 at 10:07
  • 1
    I Realized I Completely Misunderstood this Question you can use the answers suggested by matszwecja and PCastedo – mrtechtroid Apr 04 '22 at 10:09
  • please delete your comment in that case..thx – vel Apr 04 '22 at 10:10
  • There must be some buffering issue there.. – Haroldo_OK Apr 04 '22 at 10:11
  • Does this answer your question? [How to redirect 'print' output to a file?](https://stackoverflow.com/questions/7152762/how-to-redirect-print-output-to-a-file) – mrtechtroid Apr 04 '22 at 10:12

2 Answers2

2

The output sent to stdout (whether by print() or by something like sys.stdout.write()) is accumulating in a buffer. You can get it to periodically write by flushing that buffer with sys.stdout.flush():

import time
import sys

for x in range(1000):
    time.sleep(5)

    # Either sys.stdout.write or print works here
    print(x)  # sys.stdout.write(str(x))
    if x % 5 == 0:
        sys.stdout.flush()

This writes to the file where output is being redirected every five loop iterations.

In your code, you just would put sys.stdout.flush() at whichever points you would like to be able to see progress. (That may or may not be inside a loop; the one in my example is just to generate code that runs for a bit.)

baileythegreen
  • 1,126
  • 3
  • 16
  • so I just need to add line `sys.stdout.flush()` at multiple points where I would like check what was executed after specific line in the program, correct? – vel Apr 04 '22 at 10:16
  • Yep. You may also want to have some indication of where in the program things are being printed (if that isn't obvious from seeing the output), but that only matters if it's important you know where it has gotten to, rather than that it is actively doing things. – baileythegreen Apr 04 '22 at 10:19
  • is it risky to use this command too often? I see that on some other similar link: they are saying `os.fsync() is expensive`. this command cannot produce some harm if it is being used too often? https://stackoverflow.com/questions/9824806/how-come-a-file-doesnt-get-written-until-i-stop-the-program – vel Apr 04 '22 at 10:59
  • Risk is relative; I can't tell you if that's a problem for your application. It can be expensive in terms of computational resources or time, but that depends on how frequently you do it, the size of the stuff being written, et cetera. You could try different options to optimise this for your case. – baileythegreen Apr 04 '22 at 11:04
0

As @matszwecja said file.write is the best option for you. Try it yourself:

count = 0
file = open("file.txt", "a")

while(True):
    file.write(str(count) + "\n")
    count += 1
    if count == 34:
        count = 0

with this simple code you can see that while loop is running you can execute tail in another tab and it will give you output, so just change prints for file.writes (or puth both) and it will do the job.

in your code:

def main():
    """
    Script main function
    """
    file = open("log.log", "a")
    start_time = datetime.datetime.now()
    file.write ("----------------------------------------------------------------------------")
    file.write ("### script started ###")
    args = get_args()
    file.write ("depot:"+depot)
    file.write ("stream:"+args[0])
    file.write ("destination:"+args[1])

    file.write ("----------------------------------------------------------------------------")
    
    logfile = get_history(args[0])
    file.write ("----------------------------------------------------------------------------")
    
    git_migrate(logfile, args[0], args[1], args[2], args[3], depot)
    file.write ("----------------------------------------------------------------------------")        

        
    file.write ("### script completed ###")    
    end_time = datetime.datetime.now()
    file.write('Duration: {}'.format(end_time - start_time))

This way you will be able to use tail to see the file while it's being written.

PCastedo
  • 74
  • 5
  • sorry I do not understand where I need to put this???? how this is link with my `migrate.py` script which is being executed and that contains many print statements and outputs that I would like to see...? Answer is really not understandable...I will Edit the question so you could see the example of my code.. thx – vel Apr 04 '22 at 10:09
  • Sorry, it was just an example, didn't intend to confuse you more, the point is that you could change your print statements for file.write() – PCastedo Apr 04 '22 at 10:15