'Using sys.stdout to save the console output in a txt. file but keep seen the running output on the pycham console

I'm need to save some outputs that I run on the Pycharm. I know that I can use the sys.stdout to do it, but when I use it the pycharm console doesnt't show me anything until the end of the run process and I need to see the running text some times to see if something went wrong during the process.

Can someone help me with that?

What I'm using as code to redirect the console text to a .txt file:

import sys

file_path = 'log.txt'
sys.stdout = open(file_path, "w")


Solution 1:[1]

ok, I see you're trying to override sys.stdout, it wrong.

you can save something data to file, like this:

    file_path = 'log.txt'
    my_file = open(file_path, "w")
    my_file.write("some text")
    my_file.close()

you can also select a file when using the print function to write it to a file instead of sys.stdout (by default "print" writes to sys.stdout):

file_path = 'log.txt'
my_file = open(file_path, "w")
print('some text', file=my_file)
my_file.close()

Solution 2:[2]

there is a very nice trick from Mark Lutz(Learning Python), which could be useful for you. The idea here is to use a file as long as you need and then go back to normal mode. Now because you need it the other way around you could comment out all the marked parts and as soon as you're satisfied with the result, you could activate them, like this :

import sys                          # <-comment out to see the output
tmp = sys.stdout                    # <-comment out to see the output
sys.stdout = open(file_path, "w")   # <-comment out to see the output

print "something"                   # redirected to the file

sys.stdout.close()                  # <-comment out to see the output
sys.stdout = tmp                    # returns to normal mode / comment out

Solution 3:[3]

You might want to try using the python Logging library, which will allow you to save print content to the stdout console and the log file simultaneously, its much more robust and documented than the response I have included next.

The issue for yourself seems to be that when you first launch the python session the stdout stream directed to the python console, when you change stdout to be a IOStream (text file), you essentially redirect it to there; preventing any output from being sent to the python console.

If you want your own solution you can try to create a wrapper around the two streams like the one below:

import _io # For type annotations
import datetime
import sys

class Wrapper:
    def __init__(self, stdout: _io.TextIOWrapper, target_log_file: _io.TextIOWrapper):
        self.target_log_file = target_log_file
        self.stdout = stdout

    def write(self, o):
        self.target_log_file.write(o)
        self.stdout.write(o)

    def flush(self):
        self.target_log_file.flush()
        self.stdout.flush()


def main():
    file_path = 'log.txt'

    sys.stdout = Wrapper(sys.stdout, open(file_path, 'w'))

    for i in range(0, 10):
        print(f'stdout test i:{i} time:{datetime.datetime.now()}')


if __name__ == '__main__':
    main()

Solution 4:[4]

Do you need to use sys.stdout? The easiest solution may be to define a method which does both. For instance:

def print_and_export(text, path):
    print(text)
    f = open(path, 'a')
    f.write(text)
    f.close()

Then call this method from anywhere using print_and_export('Some text', 'log.txt').

But specifically for logging, I would preferably use the built in 'logging' module:

import logging

FILE_PATH = 'log.txt'
LOG_FORMAT = '[%(asctime)s] - %(filename)-30s - line %(lineno)-5d - %(levelname)-8s - %(message)s'

logging.basicConfig(level=logging.DEBUG,
                    format=LOG_FORMAT,
                    handlers=[logging.FileHandler(FILE_PATH), logging.StreamHandler()])
log = logging.getLogger()

Then you can simply call log.info("Some text"). It should print to the PyCharm console and append the text to your log file.

Solution 5:[5]

All the answers above are awesome and will give you what you are after. I have a different answer, but it will not give you both console output and file output. For that, you need to do file IO. But I'll mention my method just so you know. Make your program print the exact things you want to the console. Then, save it and open up the command prompt. You can do this by browsing to the location of the .py files, click the file path bar, type cmd which will replace all the text there and hit enter.

Once in the command prompt, type python, followed by the name of the file you want to run. Let's assume the name is myfile.py. You can write:

python myfile.py > output.txt

If you hit enter, whatever gets printed onto the console will be diverted to a .txt file named output, saved on the same folder where your .py files are. You can add parameter passing to the print() function and have errors get a different output group (stderr), and divert them to a different file. So, in the end you can make it that you have one file for normal outputs and another file for just error outputs. You can give the Python documentation a read to find it.

https://helpdeskgeek.com/how-to/redirect-output-from-command-line-to-text-file/ will help you with explaining what I am trying to describe. Could be useful for you in the future. In doing so, you are not running the code in PyCharm, but straight in the command prompt. So this way, you can literally do file IO without doing file IO. (without doing file IO in Python at least)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MNK
Solution 2 baskettaz
Solution 3 Mieszko
Solution 4
Solution 5 Some Intern Coder