6

I would like to redirect the standard error and standard output of a Python script to the same output file. From the terminal I could use

$ python myfile.py &> out.txt

to do the same task that I want, but I need to do it from the Python script itself.

I looked into the questions Redirect subprocess stderr to stdout, How to redirect stderr in Python?, and Example 10.10 from here, and then I tried the following:

import sys
fsock = open('out.txt', 'w')
sys.stdout = sys.stderr = fsock

print "a"

which rightly prints the letter "a" in the file out.txt; however, when I try the following:

import sys
fsock = open('out.txt', 'w')
sys.stdout = sys.stderr = fsock

print "a   # missing end quote, will give error

I get the error message "SyntaxError ..." on the terminal, but not in the file out.txt. What do I need to do to send the SyntaxError to the file out.txt? I do not want to write an Exception, because in that case I have to write too many Exceptions in the script. I am using Python 2.7.

Update: As pointed out in the answers and comments below, that SyntaxError will always output to screen, I replaced the line

print "a   # missing end quote, will give error

by

print 1/0  # Zero division error

The ZeroDivisionError is output to file, as I wanted to have it in my question.

jww
  • 97,681
  • 90
  • 411
  • 885
gora
  • 381
  • 3
  • 6
  • 15
  • try raising an error in your code that isn't a syntax error. After `print "a"`, raise an error like `raise ValueError('A very specific bad thing happened')` – James Russo Aug 04 '16 at 19:48
  • @JamesRusso, I would prefer not to raise Exception of any kind, for the reason I have mentioned in the question. Is there a way to emulate the bash way of "&> filename" from inside the Python script itself? – gora Aug 04 '16 at 19:55
  • I was referring to just for testing purposes... In order to test that it is working just raise an error and make sure it is being written to your file. If so all future errors should be written to the file – James Russo Aug 04 '16 at 19:58
  • @jsbueno, and James Russo, Looks like the problem was with SyntaxError. Probably other exceptions are redirected to file as I wanted. – gora Aug 04 '16 at 20:12
  • @jsbueno Does this not work in Python 3.6? I'm playing around with similar code, but nothing gets printed out the text file. – Moondra Feb 11 '18 at 20:58

2 Answers2

7

This works

sys.stdout = open('out.log', 'w')
sys.stderr = sys.stdout
yahya
  • 101
  • 1
  • 4
  • 1
    I confirm it works. I tried it with a division by zero and got the traceback and "ZeroDivisionError: division by zero" in the same log file than stdout was opened at the same time. I'm using Python 3.7.1 – Le Droid Dec 21 '19 at 03:59
3

A SyntaxError in a Python file like the above is raised before your program even begins to run: Python files are compiled just like in any other compiled language - if the parser or compiler can't find sense in your Python file, no executable bytecode is generated, therefore the program does not run.

The correct way to have an exception generated on purpose in your code - from simple test cases like yours, up to implementing complex flow control patterns, is to use the Pyton command raise.

Just leave your print there, and a line like this at the end:

raise Exception

Then you can see that your trick will work.

Your program could fail in runtime in many other ways without an explict raise, like, if you force a division by 0, or simply try to use an unassigned (and therefore "undeclared") variable - but a deliberate SyntaxError will have the effect that the program never runs to start with - not even the first few lines.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • I put the line raise Exception at the end of my script, but that still outputs to screen. I see the problem specifically with SyntaxError. In my actual script, the problem would most likely be not from syntax errors, but numerical. However, in any case, I would like to send the error to a file. – gora Aug 04 '16 at 20:00
  • well - I've just used your exact pattern and it works for me. Of course, if it is an uncaught exception that would print things on the string, that also means the program terminates at that point. But the exception traceback goes to a file. – jsbueno Aug 04 '16 at 20:10