3

I would like to print the output of python to both console and a textfile including errors, if any.

So far my attempts are these:

Using console:

# mystdout.py
# note that it has missing ) sign
print("hello


# in the terminal:
chmod a+x mystdout.py; ./mystdout.py 2>&1 | tee output.txt
# does not print to oputut.txt if mystout.py has syntax errors

Print to file (python3):

with open('out.txt', 'a') as f:  
    print('hello world', file=f)
    # this does not print to console, only to the file

Defining a class called "Tee"

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author    : Bhishan Poudel
# Date      : Jul 12, 2016


# Imports
import sys
import subprocess

##=============================================================================
class Tee(object):
    def __init__(self, *files):
        self.files = files
    def write(self, obj):
        for f in self.files:
            f.write(obj)
            f.flush() 
    def flush(self) :
        for f in self.files:
            f.flush()

f = open('out.txt', 'w')
original = sys.stdout
sys.stdout = Tee(sys.stdout, f)
##=============================================================================
print('This works good, prints all the output to both console and to a file')
print("This does not print output to file in case of syntax errors")
print("This does not print output of subprocess.call")

Question Suppose I have an executable (from C program that prints hello)

subprocess.call('./hello')
# How to print output of this executable to both console and outputfile?

Note: Code to produce executable hello

// gcc -o hello hello.c
#include<stdio.h>

int main() {
    printf("hello\n");
return 0; }

Related links:
How to redirect 'print' output to a file using python?
http://linux.byexamples.com/archives/349/how-to-redirect-output-to-a-file-as-well-as-display-it-out/
Output on the console and file using python

BhishanPoudel
  • 15,974
  • 21
  • 108
  • 169
  • Your Python script doesn't have a shebang. How is the system figuring out to have Python execute it? – jpmc26 Jul 12 '16 at 21:47
  • @jpmc26, my python script has shebang, at the top of the script, #!/usr/bin/env python or, should I use: #!/usr/bin/python ? – BhishanPoudel Jul 13 '16 at 14:45
  • Your example `mystdout.py` script in this question does not have one. The appropriate one to use depends on your environment configuration. – jpmc26 Jul 13 '16 at 15:18

3 Answers3

3

If you are using bash (minimum version 4), you can run: ./mystdout |& tee output.txt. Otherwise your suggestion ./mystdout 2>&1 | tee output.txt should also work.

Pierre
  • 6,047
  • 1
  • 30
  • 49
  • Even when you use `|&`? – Pierre Jul 12 '16 at 21:10
  • This does not have bash syntax error: chmod a+x mystdout.py; ./mystdout.py 2>&1 | tee output.txt BUT DOES NOT WORK IN CASE OF ERRROS – BhishanPoudel Jul 12 '16 at 21:21
  • ./mystdout2.py |& tee output.txt bash: syntax error near unexpected token `&' – BhishanPoudel Jul 12 '16 at 21:33
  • I have added the minimum version of bash for `|&`, sorry. Can you edit your question to explain "BUT DOES NOT WORK IN CASE OF ERRORS"? You should show the output that is displayed in your terminal but missing from `output.txt`. – Pierre Jul 13 '16 at 06:14
  • bash --version GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13), Can we make it work for bash 3.2? – BhishanPoudel Jul 13 '16 at 14:43
  • `|&` won't work, but `2>&1 |` should. As asked previously: can you edit your question to explain "BUT DOES NOT WORK IN CASE OF ERRORS"? You should show the output that is displayed in your terminal but missing from `output.txt`. – Pierre Jul 13 '16 at 15:23
3

Solution from @Pierre should work. Otherwise I would suggest intercept stdout/stderr from external process and use logging with two handlers: one for console, another for specific file. Here is and example of log configuration.

Community
  • 1
  • 1
grundic
  • 4,641
  • 3
  • 31
  • 47
  • Important if you're writing "production" code and not just a fast script: this answer is, by far, a better long-term answer than mine. – Pierre Jul 13 '16 at 06:16
0

I am using bash 3.2.53. Unfortunately the solution by Pierre does not worked for me. And solution referred by grundic was too complicated for me.

So, I came up with the easy solution:
When the python run without errors, This method worked for me:

python3 a.py | tee aout.txt

# to test other example
echo hello this is a test | tee hello.txt

# Like this it works for every commands.
BhishanPoudel
  • 15,974
  • 21
  • 108
  • 169