Redirect stdout to a file in Python?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
How do I redirect stdout to an arbitrary file in Python?
When a long-running Python script (e.g, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity.
I have already tried sys.stdout = open('somefile', 'w'), but this does not seem to prevent some external modules from still outputting to terminal (or maybe the sys.stdout = ... line did not fire at all). I know it should work from simpler scripts I've tested on, but I also didn't have time yet to test on a web application yet.
python stdout
|
show 5 more comments
How do I redirect stdout to an arbitrary file in Python?
When a long-running Python script (e.g, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity.
I have already tried sys.stdout = open('somefile', 'w'), but this does not seem to prevent some external modules from still outputting to terminal (or maybe the sys.stdout = ... line did not fire at all). I know it should work from simpler scripts I've tested on, but I also didn't have time yet to test on a web application yet.
python stdout
7
That's not really a python thing, it's a shell function. Just run your script likescript.p > file
– Falmarri
Jan 13 '11 at 0:52
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
1
@foxbunny: nohup? Why simplysomeprocess | python script.py? Why involvenohup?
– S.Lott
Jan 13 '11 at 1:39
3
Rewrite theprintstatements to apply theloggingmodule from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should notprintbutlog.
– erikbwork
Jan 3 '14 at 7:44
2
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08
|
show 5 more comments
How do I redirect stdout to an arbitrary file in Python?
When a long-running Python script (e.g, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity.
I have already tried sys.stdout = open('somefile', 'w'), but this does not seem to prevent some external modules from still outputting to terminal (or maybe the sys.stdout = ... line did not fire at all). I know it should work from simpler scripts I've tested on, but I also didn't have time yet to test on a web application yet.
python stdout
How do I redirect stdout to an arbitrary file in Python?
When a long-running Python script (e.g, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity.
I have already tried sys.stdout = open('somefile', 'w'), but this does not seem to prevent some external modules from still outputting to terminal (or maybe the sys.stdout = ... line did not fire at all). I know it should work from simpler scripts I've tested on, but I also didn't have time yet to test on a web application yet.
python stdout
python stdout
edited Oct 5 '15 at 15:17
Eric Leschinski
90.8k40331282
90.8k40331282
asked Jan 13 '11 at 0:51
hayavukhayavuk
4,92853243
4,92853243
7
That's not really a python thing, it's a shell function. Just run your script likescript.p > file
– Falmarri
Jan 13 '11 at 0:52
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
1
@foxbunny: nohup? Why simplysomeprocess | python script.py? Why involvenohup?
– S.Lott
Jan 13 '11 at 1:39
3
Rewrite theprintstatements to apply theloggingmodule from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should notprintbutlog.
– erikbwork
Jan 3 '14 at 7:44
2
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08
|
show 5 more comments
7
That's not really a python thing, it's a shell function. Just run your script likescript.p > file
– Falmarri
Jan 13 '11 at 0:52
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
1
@foxbunny: nohup? Why simplysomeprocess | python script.py? Why involvenohup?
– S.Lott
Jan 13 '11 at 1:39
3
Rewrite theprintstatements to apply theloggingmodule from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should notprintbutlog.
– erikbwork
Jan 3 '14 at 7:44
2
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08
7
7
That's not really a python thing, it's a shell function. Just run your script like
script.p > file– Falmarri
Jan 13 '11 at 0:52
That's not really a python thing, it's a shell function. Just run your script like
script.p > file– Falmarri
Jan 13 '11 at 0:52
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
1
1
@foxbunny: nohup? Why simply
someprocess | python script.py? Why involve nohup?– S.Lott
Jan 13 '11 at 1:39
@foxbunny: nohup? Why simply
someprocess | python script.py? Why involve nohup?– S.Lott
Jan 13 '11 at 1:39
3
3
Rewrite the
print statements to apply the logging module from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should not print but log.– erikbwork
Jan 3 '14 at 7:44
Rewrite the
print statements to apply the logging module from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should not print but log.– erikbwork
Jan 3 '14 at 7:44
2
2
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08
|
show 5 more comments
11 Answers
11
active
oldest
votes
If you want to do the redirection within the Python script, set sys.stdout to an file object does the trick:
import sys
sys.stdout = open('file', 'w')
print('test')
A far more common method is to use shell redirection when executing (same on Windows and Linux):
$ python foo.py > file
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
It doesn't work withfrom sys import stdout, maybe because it creates a local copy. Also you can use it withwith, e.g.with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implementfunctionThatPrints()using normalprintstatements.
– mgold
Dec 13 '12 at 0:07
33
It's best to keep a local copy,stdout = sys.stdoutso you can put it back when you're done,sys.stdout = stdout. That way if you're being called from a function that usesprintyou don't screw them up.
– mgold
Dec 20 '12 at 15:06
4
@Jan:buffering=0disables buffering (it may negatively affect performance (10-100 times)).buffering=1enables line buffering so that you could usetail -ffor a line-oriented output.
– jfs
Jul 31 '14 at 13:39
29
@mgold or you can usesys.stdout = sys.__stdout__to get it back.
– clemtoy
Jul 9 '15 at 12:52
|
show 8 more comments
There is contextlib.redirect_stdout() function in Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
It is similar to:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
that can be used on earlier Python versions. The latter version is not reusable. It can be made one if desired.
It doesn't redirect the stdout at the file descriptors level e.g.:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file.
To redirect at the file descriptor level, os.dup2() could be used:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
The same example works now if stdout_redirected() is used instead of redirect_stdout():
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected nown')
os.system('echo this is also redirected')
print('this is goes back to stdout')
The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active.
Note: stdout.flush() does not flush
C stdio buffers on Python 3 where I/O is implemented directly on read()/write() system calls. To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
You could use stdout parameter to redirect other streams, not only sys.stdout e.g., to merge sys.stderr and sys.stdout:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Example:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Note: stdout_redirected() mixes buffered I/O (sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). Beware, there could be buffering issues.
To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now.
3
stdout_redirectedis helpful. Be aware this doesn't work inside doctests, since the specialSpoofOuthandler doctest uses to replacesys.stdoutdoesn't have afilenoattribute.
– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raiseValueError("Expected a file (`.fileno()`) or a file descriptor")then it is a bug. Are you sure it doesn't raise it?
– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specifydoctest.sys.__stdout__where we would normally usesys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.
– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected()hasstdoutparameter, you could set it tosys.__stdout__if you want to redirect the original python stdout (that should have a valid.fileno()in most cases). It does nothing for the currentsys.stdoutif they are different. Don't usedoctest.sys; it is available by accident.
– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:with stdout_redirected(to=fd):with merged_stderr_stdout():print('...'); print('...', file=sys.stderr)
– neok
Sep 19 '16 at 8:36
add a comment |
you can try this too much better
import sys
class Logger(object):
def __init__(self, filename="Default.log"):
self.terminal = sys.stdout
self.log = open(filename, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt
Any suggestions for piping tologgerorsyslog?
– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.def __getattr__(self, attr): return getattr(self.terminal, attr)
– peabody
Jul 22 '14 at 22:39
3
You have to adddef flush(self):method as well to classLogger.
– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
add a comment |
The other answers didn't cover the case where you want forked processes to share your new stdout.
To do that:
from os import open, close, dup, O_WRONLY
old = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1
..... do stuff and then restore
close(1)
dup(old) # should dup to 1
close(old) # get rid of left overs
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
Insert asys.stdout.flush()before theclose(1)statement to make sure the redirect'file'file gets the output. Also, you can use atempfile.mkstemp()file in place of'file'. And be careful you don't have other threads running that can steal the os's first file handle after theos.close(1)but before the'file'is opened to use the handle.
– Alex Robinson
Nov 1 '12 at 3:59
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also useos.dup2()and wrap it into a context manager as shown in my answer
– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
add a comment |
Quoted from PEP 343 -- The "with" Statement (added import statement):
Redirect stdout temporarily:
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
Used as follows:
with open(filename, "w") as f:
with stdout_redirected(f):
print "Hello world"
This isn't thread-safe, of course, but neither is doing this same dance manually. In single-threaded programs (for example in scripts) it is a popular way of doing things.
+1. Note: it doesn't work for subprocesses e.g.,os.system('echo not redirected'). My answer shows how to redirect such output
– jfs
Mar 16 '14 at 7:43
add a comment |
import sys
sys.stdout = open('stdout.txt', 'w')
add a comment |
You need a terminal multiplexer like either tmux or GNU screen
I'm surprised that a small comment by Ryan Amos' to the original question is the only mention of a solution far preferable to all the others on offer, no matter how clever the python trickery may be and how many upvotes they've received. Further to Ryan's comment, tmux is a nice alternative to GNU screen.
But the principle is the same: if you ever find yourself wanting to leave a terminal job running while you log-out, head to the cafe for a sandwich, pop to the bathroom, go home (etc) and then later, reconnect to your terminal session from anywhere or any computer as though you'd never been away, terminal multiplexers are the answer. Think of them as VNC or remote desktop for terminal sessions. Anything else is a workaround. As a bonus, when the boss and/or partner comes in and you inadvertently ctrl-w / cmd-w your terminal window instead of your browser window with its dodgy content, you won't have lost the last 18 hours-worth of processing!
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
add a comment |
Based on this answer: https://stackoverflow.com/a/5916874/1060344, here is another way I figured out which I use in one of my projects. For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. That library may be using other methods of file object.
Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this):
class FileToLogInterface(file):
'''
Interface to make sure that everytime anything is written to stderr, it is
also forwarded to a file.
'''
def __init__(self, *args, **kwargs):
if 'cfg' not in kwargs:
raise TypeError('argument cfg is required.')
else:
if not isinstance(kwargs['cfg'], config.Config):
raise TypeError(
'argument cfg should be a valid '
'PostSegmentation configuration object i.e. '
'postsegmentation.config.Config')
self._cfg = kwargs['cfg']
kwargs.pop('cfg')
self._logger = logging.getlogger('access_log')
super(FileToLogInterface, self).__init__(*args, **kwargs)
def write(self, msg):
super(FileToLogInterface, self).write(msg)
self._logger.info(msg)
add a comment |
Programs written in other languages (e.g. C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). So, I think the best solution is to emulate them.
A plus of re-executing your program is, you can choose redirections on the command-line, e.g. /usr/bin/python mycoolscript.py 2>&1 1>/dev/null
See this post for more info: What is the reason for performing a double fork when creating a daemon?
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (systemd,upstart) or other utility (daemon(1)) to handle the forking boilerplate.
– Lucretiel
Dec 2 '14 at 5:09
add a comment |
@marcog
The second option is only good if script get excuted in a go .Or script should get executed completely only then the output goes into that file And infinite loops should`nt be present(optimally). Best solution if it is a simple script.
add a comment |
Here is a variation of Yuda Prawira answer:
- implement
flush()and all the file attributes - write it as a contextmanager
- capture
stderralso
.
import contextlib, sys
@contextlib.contextmanager
def log_print(file):
# capture all outputs to a log file while still printing it
class Logger:
def __init__(self, file):
self.terminal = sys.stdout
self.log = file
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def __getattr__(self, attr):
return getattr(self.terminal, attr)
logger = Logger(file)
_stdout = sys.stdout
_stderr = sys.stderr
sys.stdout = logger
sys.stderr = logger
try:
yield logger.log
finally:
sys.stdout = _stdout
sys.stderr = _stderr
with log_print(open('mylogfile.log', 'w')):
print('hello world')
print('hello world on stderr', file=sys.stderr)
# you can capture the output to a string with:
# with log_print(io.StringIO()) as log:
# ....
# print('[captured output]', log.getvalue())
add a comment |
11 Answers
11
active
oldest
votes
11 Answers
11
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you want to do the redirection within the Python script, set sys.stdout to an file object does the trick:
import sys
sys.stdout = open('file', 'w')
print('test')
A far more common method is to use shell redirection when executing (same on Windows and Linux):
$ python foo.py > file
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
It doesn't work withfrom sys import stdout, maybe because it creates a local copy. Also you can use it withwith, e.g.with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implementfunctionThatPrints()using normalprintstatements.
– mgold
Dec 13 '12 at 0:07
33
It's best to keep a local copy,stdout = sys.stdoutso you can put it back when you're done,sys.stdout = stdout. That way if you're being called from a function that usesprintyou don't screw them up.
– mgold
Dec 20 '12 at 15:06
4
@Jan:buffering=0disables buffering (it may negatively affect performance (10-100 times)).buffering=1enables line buffering so that you could usetail -ffor a line-oriented output.
– jfs
Jul 31 '14 at 13:39
29
@mgold or you can usesys.stdout = sys.__stdout__to get it back.
– clemtoy
Jul 9 '15 at 12:52
|
show 8 more comments
If you want to do the redirection within the Python script, set sys.stdout to an file object does the trick:
import sys
sys.stdout = open('file', 'w')
print('test')
A far more common method is to use shell redirection when executing (same on Windows and Linux):
$ python foo.py > file
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
It doesn't work withfrom sys import stdout, maybe because it creates a local copy. Also you can use it withwith, e.g.with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implementfunctionThatPrints()using normalprintstatements.
– mgold
Dec 13 '12 at 0:07
33
It's best to keep a local copy,stdout = sys.stdoutso you can put it back when you're done,sys.stdout = stdout. That way if you're being called from a function that usesprintyou don't screw them up.
– mgold
Dec 20 '12 at 15:06
4
@Jan:buffering=0disables buffering (it may negatively affect performance (10-100 times)).buffering=1enables line buffering so that you could usetail -ffor a line-oriented output.
– jfs
Jul 31 '14 at 13:39
29
@mgold or you can usesys.stdout = sys.__stdout__to get it back.
– clemtoy
Jul 9 '15 at 12:52
|
show 8 more comments
If you want to do the redirection within the Python script, set sys.stdout to an file object does the trick:
import sys
sys.stdout = open('file', 'w')
print('test')
A far more common method is to use shell redirection when executing (same on Windows and Linux):
$ python foo.py > file
If you want to do the redirection within the Python script, set sys.stdout to an file object does the trick:
import sys
sys.stdout = open('file', 'w')
print('test')
A far more common method is to use shell redirection when executing (same on Windows and Linux):
$ python foo.py > file
edited Feb 6 at 1:50
wordsforthewise
3,67422952
3,67422952
answered Jan 13 '11 at 0:53
marcogmarcog
90.2k39173209
90.2k39173209
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
It doesn't work withfrom sys import stdout, maybe because it creates a local copy. Also you can use it withwith, e.g.with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implementfunctionThatPrints()using normalprintstatements.
– mgold
Dec 13 '12 at 0:07
33
It's best to keep a local copy,stdout = sys.stdoutso you can put it back when you're done,sys.stdout = stdout. That way if you're being called from a function that usesprintyou don't screw them up.
– mgold
Dec 20 '12 at 15:06
4
@Jan:buffering=0disables buffering (it may negatively affect performance (10-100 times)).buffering=1enables line buffering so that you could usetail -ffor a line-oriented output.
– jfs
Jul 31 '14 at 13:39
29
@mgold or you can usesys.stdout = sys.__stdout__to get it back.
– clemtoy
Jul 9 '15 at 12:52
|
show 8 more comments
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
It doesn't work withfrom sys import stdout, maybe because it creates a local copy. Also you can use it withwith, e.g.with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implementfunctionThatPrints()using normalprintstatements.
– mgold
Dec 13 '12 at 0:07
33
It's best to keep a local copy,stdout = sys.stdoutso you can put it back when you're done,sys.stdout = stdout. That way if you're being called from a function that usesprintyou don't screw them up.
– mgold
Dec 20 '12 at 15:06
4
@Jan:buffering=0disables buffering (it may negatively affect performance (10-100 times)).buffering=1enables line buffering so that you could usetail -ffor a line-oriented output.
– jfs
Jul 31 '14 at 13:39
29
@mgold or you can usesys.stdout = sys.__stdout__to get it back.
– clemtoy
Jul 9 '15 at 12:52
3
3
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
If you're on Windows watch out for Windows bug - Cannot redirect output when I run Python script on Windows using just script's name
– Piotr Dobrogost
Oct 4 '12 at 11:00
5
5
It doesn't work with
from sys import stdout, maybe because it creates a local copy. Also you can use it with with, e.g. with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implement functionThatPrints() using normal print statements.– mgold
Dec 13 '12 at 0:07
It doesn't work with
from sys import stdout, maybe because it creates a local copy. Also you can use it with with, e.g. with open('file', 'w') as sys.stdout: functionThatPrints(). You can now implement functionThatPrints() using normal print statements.– mgold
Dec 13 '12 at 0:07
33
33
It's best to keep a local copy,
stdout = sys.stdout so you can put it back when you're done, sys.stdout = stdout. That way if you're being called from a function that uses print you don't screw them up.– mgold
Dec 20 '12 at 15:06
It's best to keep a local copy,
stdout = sys.stdout so you can put it back when you're done, sys.stdout = stdout. That way if you're being called from a function that uses print you don't screw them up.– mgold
Dec 20 '12 at 15:06
4
4
@Jan:
buffering=0 disables buffering (it may negatively affect performance (10-100 times)). buffering=1 enables line buffering so that you could use tail -f for a line-oriented output.– jfs
Jul 31 '14 at 13:39
@Jan:
buffering=0 disables buffering (it may negatively affect performance (10-100 times)). buffering=1 enables line buffering so that you could use tail -f for a line-oriented output.– jfs
Jul 31 '14 at 13:39
29
29
@mgold or you can use
sys.stdout = sys.__stdout__ to get it back.– clemtoy
Jul 9 '15 at 12:52
@mgold or you can use
sys.stdout = sys.__stdout__ to get it back.– clemtoy
Jul 9 '15 at 12:52
|
show 8 more comments
There is contextlib.redirect_stdout() function in Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
It is similar to:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
that can be used on earlier Python versions. The latter version is not reusable. It can be made one if desired.
It doesn't redirect the stdout at the file descriptors level e.g.:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file.
To redirect at the file descriptor level, os.dup2() could be used:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
The same example works now if stdout_redirected() is used instead of redirect_stdout():
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected nown')
os.system('echo this is also redirected')
print('this is goes back to stdout')
The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active.
Note: stdout.flush() does not flush
C stdio buffers on Python 3 where I/O is implemented directly on read()/write() system calls. To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
You could use stdout parameter to redirect other streams, not only sys.stdout e.g., to merge sys.stderr and sys.stdout:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Example:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Note: stdout_redirected() mixes buffered I/O (sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). Beware, there could be buffering issues.
To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now.
3
stdout_redirectedis helpful. Be aware this doesn't work inside doctests, since the specialSpoofOuthandler doctest uses to replacesys.stdoutdoesn't have afilenoattribute.
– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raiseValueError("Expected a file (`.fileno()`) or a file descriptor")then it is a bug. Are you sure it doesn't raise it?
– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specifydoctest.sys.__stdout__where we would normally usesys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.
– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected()hasstdoutparameter, you could set it tosys.__stdout__if you want to redirect the original python stdout (that should have a valid.fileno()in most cases). It does nothing for the currentsys.stdoutif they are different. Don't usedoctest.sys; it is available by accident.
– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:with stdout_redirected(to=fd):with merged_stderr_stdout():print('...'); print('...', file=sys.stderr)
– neok
Sep 19 '16 at 8:36
add a comment |
There is contextlib.redirect_stdout() function in Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
It is similar to:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
that can be used on earlier Python versions. The latter version is not reusable. It can be made one if desired.
It doesn't redirect the stdout at the file descriptors level e.g.:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file.
To redirect at the file descriptor level, os.dup2() could be used:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
The same example works now if stdout_redirected() is used instead of redirect_stdout():
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected nown')
os.system('echo this is also redirected')
print('this is goes back to stdout')
The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active.
Note: stdout.flush() does not flush
C stdio buffers on Python 3 where I/O is implemented directly on read()/write() system calls. To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
You could use stdout parameter to redirect other streams, not only sys.stdout e.g., to merge sys.stderr and sys.stdout:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Example:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Note: stdout_redirected() mixes buffered I/O (sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). Beware, there could be buffering issues.
To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now.
3
stdout_redirectedis helpful. Be aware this doesn't work inside doctests, since the specialSpoofOuthandler doctest uses to replacesys.stdoutdoesn't have afilenoattribute.
– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raiseValueError("Expected a file (`.fileno()`) or a file descriptor")then it is a bug. Are you sure it doesn't raise it?
– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specifydoctest.sys.__stdout__where we would normally usesys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.
– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected()hasstdoutparameter, you could set it tosys.__stdout__if you want to redirect the original python stdout (that should have a valid.fileno()in most cases). It does nothing for the currentsys.stdoutif they are different. Don't usedoctest.sys; it is available by accident.
– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:with stdout_redirected(to=fd):with merged_stderr_stdout():print('...'); print('...', file=sys.stderr)
– neok
Sep 19 '16 at 8:36
add a comment |
There is contextlib.redirect_stdout() function in Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
It is similar to:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
that can be used on earlier Python versions. The latter version is not reusable. It can be made one if desired.
It doesn't redirect the stdout at the file descriptors level e.g.:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file.
To redirect at the file descriptor level, os.dup2() could be used:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
The same example works now if stdout_redirected() is used instead of redirect_stdout():
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected nown')
os.system('echo this is also redirected')
print('this is goes back to stdout')
The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active.
Note: stdout.flush() does not flush
C stdio buffers on Python 3 where I/O is implemented directly on read()/write() system calls. To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
You could use stdout parameter to redirect other streams, not only sys.stdout e.g., to merge sys.stderr and sys.stdout:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Example:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Note: stdout_redirected() mixes buffered I/O (sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). Beware, there could be buffering issues.
To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now.
There is contextlib.redirect_stdout() function in Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
It is similar to:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
that can be used on earlier Python versions. The latter version is not reusable. It can be made one if desired.
It doesn't redirect the stdout at the file descriptors level e.g.:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file.
To redirect at the file descriptor level, os.dup2() could be used:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
The same example works now if stdout_redirected() is used instead of redirect_stdout():
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected nown')
os.system('echo this is also redirected')
print('this is goes back to stdout')
The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active.
Note: stdout.flush() does not flush
C stdio buffers on Python 3 where I/O is implemented directly on read()/write() system calls. To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
You could use stdout parameter to redirect other streams, not only sys.stdout e.g., to merge sys.stderr and sys.stdout:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Example:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Note: stdout_redirected() mixes buffered I/O (sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). Beware, there could be buffering issues.
To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now.
edited May 23 '17 at 12:26
Community♦
11
11
answered Mar 16 '14 at 7:39
jfsjfs
273k825791136
273k825791136
3
stdout_redirectedis helpful. Be aware this doesn't work inside doctests, since the specialSpoofOuthandler doctest uses to replacesys.stdoutdoesn't have afilenoattribute.
– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raiseValueError("Expected a file (`.fileno()`) or a file descriptor")then it is a bug. Are you sure it doesn't raise it?
– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specifydoctest.sys.__stdout__where we would normally usesys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.
– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected()hasstdoutparameter, you could set it tosys.__stdout__if you want to redirect the original python stdout (that should have a valid.fileno()in most cases). It does nothing for the currentsys.stdoutif they are different. Don't usedoctest.sys; it is available by accident.
– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:with stdout_redirected(to=fd):with merged_stderr_stdout():print('...'); print('...', file=sys.stderr)
– neok
Sep 19 '16 at 8:36
add a comment |
3
stdout_redirectedis helpful. Be aware this doesn't work inside doctests, since the specialSpoofOuthandler doctest uses to replacesys.stdoutdoesn't have afilenoattribute.
– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raiseValueError("Expected a file (`.fileno()`) or a file descriptor")then it is a bug. Are you sure it doesn't raise it?
– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specifydoctest.sys.__stdout__where we would normally usesys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.
– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected()hasstdoutparameter, you could set it tosys.__stdout__if you want to redirect the original python stdout (that should have a valid.fileno()in most cases). It does nothing for the currentsys.stdoutif they are different. Don't usedoctest.sys; it is available by accident.
– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:with stdout_redirected(to=fd):with merged_stderr_stdout():print('...'); print('...', file=sys.stderr)
– neok
Sep 19 '16 at 8:36
3
3
stdout_redirected is helpful. Be aware this doesn't work inside doctests, since the special SpoofOut handler doctest uses to replace sys.stdout doesn't have a fileno attribute.– Chris Johnson
Apr 21 '14 at 15:47
stdout_redirected is helpful. Be aware this doesn't work inside doctests, since the special SpoofOut handler doctest uses to replace sys.stdout doesn't have a fileno attribute.– Chris Johnson
Apr 21 '14 at 15:47
@ChrisJohnson: If it doesn't raise
ValueError("Expected a file (`.fileno()`) or a file descriptor") then it is a bug. Are you sure it doesn't raise it?– jfs
Apr 21 '14 at 16:37
@ChrisJohnson: If it doesn't raise
ValueError("Expected a file (`.fileno()`) or a file descriptor") then it is a bug. Are you sure it doesn't raise it?– jfs
Apr 21 '14 at 16:37
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specify
doctest.sys.__stdout__ where we would normally use sys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.– Chris Johnson
Apr 21 '14 at 19:42
It does raise that error, which is what make it not usable within a doctest. To use your function within a doctest, it appears necessary to specify
doctest.sys.__stdout__ where we would normally use sys.stdout. This isn't a problem with your function, just an accommodation required for doctest since it replaces stdout with an object that doesn't have all the attributes a true file would.– Chris Johnson
Apr 21 '14 at 19:42
stdout_redirected() has stdout parameter, you could set it to sys.__stdout__ if you want to redirect the original python stdout (that should have a valid .fileno() in most cases). It does nothing for the current sys.stdout if they are different. Don't use doctest.sys; it is available by accident.– jfs
Apr 21 '14 at 19:48
stdout_redirected() has stdout parameter, you could set it to sys.__stdout__ if you want to redirect the original python stdout (that should have a valid .fileno() in most cases). It does nothing for the current sys.stdout if they are different. Don't use doctest.sys; it is available by accident.– jfs
Apr 21 '14 at 19:48
This really works well, i.e. redirect stdout and stderr to a fd:
with stdout_redirected(to=fd): with merged_stderr_stdout(): print('...'); print('...', file=sys.stderr)– neok
Sep 19 '16 at 8:36
This really works well, i.e. redirect stdout and stderr to a fd:
with stdout_redirected(to=fd): with merged_stderr_stdout(): print('...'); print('...', file=sys.stderr)– neok
Sep 19 '16 at 8:36
add a comment |
you can try this too much better
import sys
class Logger(object):
def __init__(self, filename="Default.log"):
self.terminal = sys.stdout
self.log = open(filename, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt
Any suggestions for piping tologgerorsyslog?
– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.def __getattr__(self, attr): return getattr(self.terminal, attr)
– peabody
Jul 22 '14 at 22:39
3
You have to adddef flush(self):method as well to classLogger.
– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
add a comment |
you can try this too much better
import sys
class Logger(object):
def __init__(self, filename="Default.log"):
self.terminal = sys.stdout
self.log = open(filename, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt
Any suggestions for piping tologgerorsyslog?
– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.def __getattr__(self, attr): return getattr(self.terminal, attr)
– peabody
Jul 22 '14 at 22:39
3
You have to adddef flush(self):method as well to classLogger.
– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
add a comment |
you can try this too much better
import sys
class Logger(object):
def __init__(self, filename="Default.log"):
self.terminal = sys.stdout
self.log = open(filename, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt
you can try this too much better
import sys
class Logger(object):
def __init__(self, filename="Default.log"):
self.terminal = sys.stdout
self.log = open(filename, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt
edited May 10 '13 at 0:35
Oleksiy
4,30212844
4,30212844
answered May 6 '11 at 20:49
Yuda PrawiraYuda Prawira
6,41273447
6,41273447
Any suggestions for piping tologgerorsyslog?
– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.def __getattr__(self, attr): return getattr(self.terminal, attr)
– peabody
Jul 22 '14 at 22:39
3
You have to adddef flush(self):method as well to classLogger.
– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
add a comment |
Any suggestions for piping tologgerorsyslog?
– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.def __getattr__(self, attr): return getattr(self.terminal, attr)
– peabody
Jul 22 '14 at 22:39
3
You have to adddef flush(self):method as well to classLogger.
– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
Any suggestions for piping to
logger or syslog?– dsummersl
Mar 8 '13 at 17:08
Any suggestions for piping to
logger or syslog?– dsummersl
Mar 8 '13 at 17:08
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
If you want to edit a file this isn't very useful. Anyway +1 for the nice trick
– aIKid
Mar 20 '14 at 5:41
7
7
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.
def __getattr__(self, attr): return getattr(self.terminal, attr)– peabody
Jul 22 '14 at 22:39
This will have consequences for code which assumes sys.stdout is a full fledged file object with methods such as fileno() (which includes code in the python standard library). I would add a __getattr__(self, attr) method to that which defers attribute lookup to self.terminal.
def __getattr__(self, attr): return getattr(self.terminal, attr)– peabody
Jul 22 '14 at 22:39
3
3
You have to add
def flush(self): method as well to class Logger.– loretoparisi
Aug 3 '17 at 14:13
You have to add
def flush(self): method as well to class Logger.– loretoparisi
Aug 3 '17 at 14:13
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
This helped me setup logging to both stdout and a file: docs.python.org/3/howto/logging-cookbook.html
– colllin
Mar 15 '18 at 17:27
add a comment |
The other answers didn't cover the case where you want forked processes to share your new stdout.
To do that:
from os import open, close, dup, O_WRONLY
old = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1
..... do stuff and then restore
close(1)
dup(old) # should dup to 1
close(old) # get rid of left overs
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
Insert asys.stdout.flush()before theclose(1)statement to make sure the redirect'file'file gets the output. Also, you can use atempfile.mkstemp()file in place of'file'. And be careful you don't have other threads running that can steal the os's first file handle after theos.close(1)but before the'file'is opened to use the handle.
– Alex Robinson
Nov 1 '12 at 3:59
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also useos.dup2()and wrap it into a context manager as shown in my answer
– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
add a comment |
The other answers didn't cover the case where you want forked processes to share your new stdout.
To do that:
from os import open, close, dup, O_WRONLY
old = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1
..... do stuff and then restore
close(1)
dup(old) # should dup to 1
close(old) # get rid of left overs
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
Insert asys.stdout.flush()before theclose(1)statement to make sure the redirect'file'file gets the output. Also, you can use atempfile.mkstemp()file in place of'file'. And be careful you don't have other threads running that can steal the os's first file handle after theos.close(1)but before the'file'is opened to use the handle.
– Alex Robinson
Nov 1 '12 at 3:59
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also useos.dup2()and wrap it into a context manager as shown in my answer
– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
add a comment |
The other answers didn't cover the case where you want forked processes to share your new stdout.
To do that:
from os import open, close, dup, O_WRONLY
old = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1
..... do stuff and then restore
close(1)
dup(old) # should dup to 1
close(old) # get rid of left overs
The other answers didn't cover the case where you want forked processes to share your new stdout.
To do that:
from os import open, close, dup, O_WRONLY
old = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1
..... do stuff and then restore
close(1)
dup(old) # should dup to 1
close(old) # get rid of left overs
edited Mar 15 '14 at 0:04
Thomas
6,89542032
6,89542032
answered Jul 24 '12 at 14:24
Yam MarcovicYam Marcovic
6,5422036
6,5422036
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
Insert asys.stdout.flush()before theclose(1)statement to make sure the redirect'file'file gets the output. Also, you can use atempfile.mkstemp()file in place of'file'. And be careful you don't have other threads running that can steal the os's first file handle after theos.close(1)but before the'file'is opened to use the handle.
– Alex Robinson
Nov 1 '12 at 3:59
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also useos.dup2()and wrap it into a context manager as shown in my answer
– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
add a comment |
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
Insert asys.stdout.flush()before theclose(1)statement to make sure the redirect'file'file gets the output. Also, you can use atempfile.mkstemp()file in place of'file'. And be careful you don't have other threads running that can steal the os's first file handle after theos.close(1)but before the'file'is opened to use the handle.
– Alex Robinson
Nov 1 '12 at 3:59
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also useos.dup2()and wrap it into a context manager as shown in my answer
– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
3
3
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
one needs to replace the 'w' attribute with, os.O_WRONLY|os.O_CREATE ... can't send strings into the "os" commands!
– Ch'marr
Jul 26 '12 at 21:52
3
3
Insert a
sys.stdout.flush() before the close(1) statement to make sure the redirect 'file' file gets the output. Also, you can use a tempfile.mkstemp() file in place of 'file'. And be careful you don't have other threads running that can steal the os's first file handle after the os.close(1) but before the 'file' is opened to use the handle.– Alex Robinson
Nov 1 '12 at 3:59
Insert a
sys.stdout.flush() before the close(1) statement to make sure the redirect 'file' file gets the output. Also, you can use a tempfile.mkstemp() file in place of 'file'. And be careful you don't have other threads running that can steal the os's first file handle after the os.close(1) but before the 'file' is opened to use the handle.– Alex Robinson
Nov 1 '12 at 3:59
2
2
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
its os.O_WRONLY | os.O_CREAT ... there is no E on there.
– Jeff Sheffield
Jan 26 '14 at 5:16
+1. You could also use
os.dup2() and wrap it into a context manager as shown in my answer– jfs
Mar 16 '14 at 7:46
+1. You could also use
os.dup2() and wrap it into a context manager as shown in my answer– jfs
Mar 16 '14 at 7:46
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
@Ch'marr It's O_CREAT, not O_CREATE.
– quant_dev
Nov 17 '16 at 9:51
add a comment |
Quoted from PEP 343 -- The "with" Statement (added import statement):
Redirect stdout temporarily:
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
Used as follows:
with open(filename, "w") as f:
with stdout_redirected(f):
print "Hello world"
This isn't thread-safe, of course, but neither is doing this same dance manually. In single-threaded programs (for example in scripts) it is a popular way of doing things.
+1. Note: it doesn't work for subprocesses e.g.,os.system('echo not redirected'). My answer shows how to redirect such output
– jfs
Mar 16 '14 at 7:43
add a comment |
Quoted from PEP 343 -- The "with" Statement (added import statement):
Redirect stdout temporarily:
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
Used as follows:
with open(filename, "w") as f:
with stdout_redirected(f):
print "Hello world"
This isn't thread-safe, of course, but neither is doing this same dance manually. In single-threaded programs (for example in scripts) it is a popular way of doing things.
+1. Note: it doesn't work for subprocesses e.g.,os.system('echo not redirected'). My answer shows how to redirect such output
– jfs
Mar 16 '14 at 7:43
add a comment |
Quoted from PEP 343 -- The "with" Statement (added import statement):
Redirect stdout temporarily:
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
Used as follows:
with open(filename, "w") as f:
with stdout_redirected(f):
print "Hello world"
This isn't thread-safe, of course, but neither is doing this same dance manually. In single-threaded programs (for example in scripts) it is a popular way of doing things.
Quoted from PEP 343 -- The "with" Statement (added import statement):
Redirect stdout temporarily:
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
Used as follows:
with open(filename, "w") as f:
with stdout_redirected(f):
print "Hello world"
This isn't thread-safe, of course, but neither is doing this same dance manually. In single-threaded programs (for example in scripts) it is a popular way of doing things.
edited Jun 6 '18 at 13:07
Georgy
2,34241729
2,34241729
answered Feb 5 '13 at 12:09
GerliGerli
35146
35146
+1. Note: it doesn't work for subprocesses e.g.,os.system('echo not redirected'). My answer shows how to redirect such output
– jfs
Mar 16 '14 at 7:43
add a comment |
+1. Note: it doesn't work for subprocesses e.g.,os.system('echo not redirected'). My answer shows how to redirect such output
– jfs
Mar 16 '14 at 7:43
+1. Note: it doesn't work for subprocesses e.g.,
os.system('echo not redirected'). My answer shows how to redirect such output– jfs
Mar 16 '14 at 7:43
+1. Note: it doesn't work for subprocesses e.g.,
os.system('echo not redirected'). My answer shows how to redirect such output– jfs
Mar 16 '14 at 7:43
add a comment |
import sys
sys.stdout = open('stdout.txt', 'w')
add a comment |
import sys
sys.stdout = open('stdout.txt', 'w')
add a comment |
import sys
sys.stdout = open('stdout.txt', 'w')
import sys
sys.stdout = open('stdout.txt', 'w')
answered Jan 13 '11 at 0:52
Cat Plus PlusCat Plus Plus
93.3k23169203
93.3k23169203
add a comment |
add a comment |
You need a terminal multiplexer like either tmux or GNU screen
I'm surprised that a small comment by Ryan Amos' to the original question is the only mention of a solution far preferable to all the others on offer, no matter how clever the python trickery may be and how many upvotes they've received. Further to Ryan's comment, tmux is a nice alternative to GNU screen.
But the principle is the same: if you ever find yourself wanting to leave a terminal job running while you log-out, head to the cafe for a sandwich, pop to the bathroom, go home (etc) and then later, reconnect to your terminal session from anywhere or any computer as though you'd never been away, terminal multiplexers are the answer. Think of them as VNC or remote desktop for terminal sessions. Anything else is a workaround. As a bonus, when the boss and/or partner comes in and you inadvertently ctrl-w / cmd-w your terminal window instead of your browser window with its dodgy content, you won't have lost the last 18 hours-worth of processing!
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
add a comment |
You need a terminal multiplexer like either tmux or GNU screen
I'm surprised that a small comment by Ryan Amos' to the original question is the only mention of a solution far preferable to all the others on offer, no matter how clever the python trickery may be and how many upvotes they've received. Further to Ryan's comment, tmux is a nice alternative to GNU screen.
But the principle is the same: if you ever find yourself wanting to leave a terminal job running while you log-out, head to the cafe for a sandwich, pop to the bathroom, go home (etc) and then later, reconnect to your terminal session from anywhere or any computer as though you'd never been away, terminal multiplexers are the answer. Think of them as VNC or remote desktop for terminal sessions. Anything else is a workaround. As a bonus, when the boss and/or partner comes in and you inadvertently ctrl-w / cmd-w your terminal window instead of your browser window with its dodgy content, you won't have lost the last 18 hours-worth of processing!
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
add a comment |
You need a terminal multiplexer like either tmux or GNU screen
I'm surprised that a small comment by Ryan Amos' to the original question is the only mention of a solution far preferable to all the others on offer, no matter how clever the python trickery may be and how many upvotes they've received. Further to Ryan's comment, tmux is a nice alternative to GNU screen.
But the principle is the same: if you ever find yourself wanting to leave a terminal job running while you log-out, head to the cafe for a sandwich, pop to the bathroom, go home (etc) and then later, reconnect to your terminal session from anywhere or any computer as though you'd never been away, terminal multiplexers are the answer. Think of them as VNC or remote desktop for terminal sessions. Anything else is a workaround. As a bonus, when the boss and/or partner comes in and you inadvertently ctrl-w / cmd-w your terminal window instead of your browser window with its dodgy content, you won't have lost the last 18 hours-worth of processing!
You need a terminal multiplexer like either tmux or GNU screen
I'm surprised that a small comment by Ryan Amos' to the original question is the only mention of a solution far preferable to all the others on offer, no matter how clever the python trickery may be and how many upvotes they've received. Further to Ryan's comment, tmux is a nice alternative to GNU screen.
But the principle is the same: if you ever find yourself wanting to leave a terminal job running while you log-out, head to the cafe for a sandwich, pop to the bathroom, go home (etc) and then later, reconnect to your terminal session from anywhere or any computer as though you'd never been away, terminal multiplexers are the answer. Think of them as VNC or remote desktop for terminal sessions. Anything else is a workaround. As a bonus, when the boss and/or partner comes in and you inadvertently ctrl-w / cmd-w your terminal window instead of your browser window with its dodgy content, you won't have lost the last 18 hours-worth of processing!
edited Aug 23 '17 at 5:17
jfs
273k825791136
273k825791136
answered May 17 '15 at 14:13
duncanduncan
1,27621019
1,27621019
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
add a comment |
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
2
2
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
while it is a good answer for the part of the question appeared after the edit; it does not answer the question in the title (most people come here from google for the title)
– jfs
Jul 15 '15 at 14:01
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
That's a fair point, and one I hadn't considered.
– duncan
Jul 15 '15 at 17:57
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
It looks like tmux has moved to tmux.github.io
– Teepeemm
Mar 3 '17 at 3:19
add a comment |
Based on this answer: https://stackoverflow.com/a/5916874/1060344, here is another way I figured out which I use in one of my projects. For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. That library may be using other methods of file object.
Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this):
class FileToLogInterface(file):
'''
Interface to make sure that everytime anything is written to stderr, it is
also forwarded to a file.
'''
def __init__(self, *args, **kwargs):
if 'cfg' not in kwargs:
raise TypeError('argument cfg is required.')
else:
if not isinstance(kwargs['cfg'], config.Config):
raise TypeError(
'argument cfg should be a valid '
'PostSegmentation configuration object i.e. '
'postsegmentation.config.Config')
self._cfg = kwargs['cfg']
kwargs.pop('cfg')
self._logger = logging.getlogger('access_log')
super(FileToLogInterface, self).__init__(*args, **kwargs)
def write(self, msg):
super(FileToLogInterface, self).write(msg)
self._logger.info(msg)
add a comment |
Based on this answer: https://stackoverflow.com/a/5916874/1060344, here is another way I figured out which I use in one of my projects. For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. That library may be using other methods of file object.
Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this):
class FileToLogInterface(file):
'''
Interface to make sure that everytime anything is written to stderr, it is
also forwarded to a file.
'''
def __init__(self, *args, **kwargs):
if 'cfg' not in kwargs:
raise TypeError('argument cfg is required.')
else:
if not isinstance(kwargs['cfg'], config.Config):
raise TypeError(
'argument cfg should be a valid '
'PostSegmentation configuration object i.e. '
'postsegmentation.config.Config')
self._cfg = kwargs['cfg']
kwargs.pop('cfg')
self._logger = logging.getlogger('access_log')
super(FileToLogInterface, self).__init__(*args, **kwargs)
def write(self, msg):
super(FileToLogInterface, self).write(msg)
self._logger.info(msg)
add a comment |
Based on this answer: https://stackoverflow.com/a/5916874/1060344, here is another way I figured out which I use in one of my projects. For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. That library may be using other methods of file object.
Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this):
class FileToLogInterface(file):
'''
Interface to make sure that everytime anything is written to stderr, it is
also forwarded to a file.
'''
def __init__(self, *args, **kwargs):
if 'cfg' not in kwargs:
raise TypeError('argument cfg is required.')
else:
if not isinstance(kwargs['cfg'], config.Config):
raise TypeError(
'argument cfg should be a valid '
'PostSegmentation configuration object i.e. '
'postsegmentation.config.Config')
self._cfg = kwargs['cfg']
kwargs.pop('cfg')
self._logger = logging.getlogger('access_log')
super(FileToLogInterface, self).__init__(*args, **kwargs)
def write(self, msg):
super(FileToLogInterface, self).write(msg)
self._logger.info(msg)
Based on this answer: https://stackoverflow.com/a/5916874/1060344, here is another way I figured out which I use in one of my projects. For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. That library may be using other methods of file object.
Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this):
class FileToLogInterface(file):
'''
Interface to make sure that everytime anything is written to stderr, it is
also forwarded to a file.
'''
def __init__(self, *args, **kwargs):
if 'cfg' not in kwargs:
raise TypeError('argument cfg is required.')
else:
if not isinstance(kwargs['cfg'], config.Config):
raise TypeError(
'argument cfg should be a valid '
'PostSegmentation configuration object i.e. '
'postsegmentation.config.Config')
self._cfg = kwargs['cfg']
kwargs.pop('cfg')
self._logger = logging.getlogger('access_log')
super(FileToLogInterface, self).__init__(*args, **kwargs)
def write(self, msg):
super(FileToLogInterface, self).write(msg)
self._logger.info(msg)
edited May 23 '17 at 11:33
Community♦
11
11
answered Jan 30 '15 at 12:48
vaidikvaidik
1,54011120
1,54011120
add a comment |
add a comment |
Programs written in other languages (e.g. C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). So, I think the best solution is to emulate them.
A plus of re-executing your program is, you can choose redirections on the command-line, e.g. /usr/bin/python mycoolscript.py 2>&1 1>/dev/null
See this post for more info: What is the reason for performing a double fork when creating a daemon?
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (systemd,upstart) or other utility (daemon(1)) to handle the forking boilerplate.
– Lucretiel
Dec 2 '14 at 5:09
add a comment |
Programs written in other languages (e.g. C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). So, I think the best solution is to emulate them.
A plus of re-executing your program is, you can choose redirections on the command-line, e.g. /usr/bin/python mycoolscript.py 2>&1 1>/dev/null
See this post for more info: What is the reason for performing a double fork when creating a daemon?
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (systemd,upstart) or other utility (daemon(1)) to handle the forking boilerplate.
– Lucretiel
Dec 2 '14 at 5:09
add a comment |
Programs written in other languages (e.g. C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). So, I think the best solution is to emulate them.
A plus of re-executing your program is, you can choose redirections on the command-line, e.g. /usr/bin/python mycoolscript.py 2>&1 1>/dev/null
See this post for more info: What is the reason for performing a double fork when creating a daemon?
Programs written in other languages (e.g. C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). So, I think the best solution is to emulate them.
A plus of re-executing your program is, you can choose redirections on the command-line, e.g. /usr/bin/python mycoolscript.py 2>&1 1>/dev/null
See this post for more info: What is the reason for performing a double fork when creating a daemon?
edited May 23 '17 at 12:10
Community♦
11
11
answered Jun 8 '13 at 17:23
jpaughjpaugh
3,96632569
3,96632569
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (systemd,upstart) or other utility (daemon(1)) to handle the forking boilerplate.
– Lucretiel
Dec 2 '14 at 5:09
add a comment |
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (systemd,upstart) or other utility (daemon(1)) to handle the forking boilerplate.
– Lucretiel
Dec 2 '14 at 5:09
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (
systemd, upstart) or other utility (daemon(1)) to handle the forking boilerplate.– Lucretiel
Dec 2 '14 at 5:09
Eh... can't say I'm a fan of processes managing their own double-forking. It's so common an idiom, and so easy to code wrong if you aren't careful. Better to write your process to run in the foreground, and use a system background task manager (
systemd, upstart) or other utility (daemon(1)) to handle the forking boilerplate.– Lucretiel
Dec 2 '14 at 5:09
add a comment |
@marcog
The second option is only good if script get excuted in a go .Or script should get executed completely only then the output goes into that file And infinite loops should`nt be present(optimally). Best solution if it is a simple script.
add a comment |
@marcog
The second option is only good if script get excuted in a go .Or script should get executed completely only then the output goes into that file And infinite loops should`nt be present(optimally). Best solution if it is a simple script.
add a comment |
@marcog
The second option is only good if script get excuted in a go .Or script should get executed completely only then the output goes into that file And infinite loops should`nt be present(optimally). Best solution if it is a simple script.
@marcog
The second option is only good if script get excuted in a go .Or script should get executed completely only then the output goes into that file And infinite loops should`nt be present(optimally). Best solution if it is a simple script.
edited Nov 25 '18 at 5:10
answered Nov 25 '18 at 5:01
yunusyunus
67149
67149
add a comment |
add a comment |
Here is a variation of Yuda Prawira answer:
- implement
flush()and all the file attributes - write it as a contextmanager
- capture
stderralso
.
import contextlib, sys
@contextlib.contextmanager
def log_print(file):
# capture all outputs to a log file while still printing it
class Logger:
def __init__(self, file):
self.terminal = sys.stdout
self.log = file
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def __getattr__(self, attr):
return getattr(self.terminal, attr)
logger = Logger(file)
_stdout = sys.stdout
_stderr = sys.stderr
sys.stdout = logger
sys.stderr = logger
try:
yield logger.log
finally:
sys.stdout = _stdout
sys.stderr = _stderr
with log_print(open('mylogfile.log', 'w')):
print('hello world')
print('hello world on stderr', file=sys.stderr)
# you can capture the output to a string with:
# with log_print(io.StringIO()) as log:
# ....
# print('[captured output]', log.getvalue())
add a comment |
Here is a variation of Yuda Prawira answer:
- implement
flush()and all the file attributes - write it as a contextmanager
- capture
stderralso
.
import contextlib, sys
@contextlib.contextmanager
def log_print(file):
# capture all outputs to a log file while still printing it
class Logger:
def __init__(self, file):
self.terminal = sys.stdout
self.log = file
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def __getattr__(self, attr):
return getattr(self.terminal, attr)
logger = Logger(file)
_stdout = sys.stdout
_stderr = sys.stderr
sys.stdout = logger
sys.stderr = logger
try:
yield logger.log
finally:
sys.stdout = _stdout
sys.stderr = _stderr
with log_print(open('mylogfile.log', 'w')):
print('hello world')
print('hello world on stderr', file=sys.stderr)
# you can capture the output to a string with:
# with log_print(io.StringIO()) as log:
# ....
# print('[captured output]', log.getvalue())
add a comment |
Here is a variation of Yuda Prawira answer:
- implement
flush()and all the file attributes - write it as a contextmanager
- capture
stderralso
.
import contextlib, sys
@contextlib.contextmanager
def log_print(file):
# capture all outputs to a log file while still printing it
class Logger:
def __init__(self, file):
self.terminal = sys.stdout
self.log = file
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def __getattr__(self, attr):
return getattr(self.terminal, attr)
logger = Logger(file)
_stdout = sys.stdout
_stderr = sys.stderr
sys.stdout = logger
sys.stderr = logger
try:
yield logger.log
finally:
sys.stdout = _stdout
sys.stderr = _stderr
with log_print(open('mylogfile.log', 'w')):
print('hello world')
print('hello world on stderr', file=sys.stderr)
# you can capture the output to a string with:
# with log_print(io.StringIO()) as log:
# ....
# print('[captured output]', log.getvalue())
Here is a variation of Yuda Prawira answer:
- implement
flush()and all the file attributes - write it as a contextmanager
- capture
stderralso
.
import contextlib, sys
@contextlib.contextmanager
def log_print(file):
# capture all outputs to a log file while still printing it
class Logger:
def __init__(self, file):
self.terminal = sys.stdout
self.log = file
def write(self, message):
self.terminal.write(message)
self.log.write(message)
def __getattr__(self, attr):
return getattr(self.terminal, attr)
logger = Logger(file)
_stdout = sys.stdout
_stderr = sys.stderr
sys.stdout = logger
sys.stderr = logger
try:
yield logger.log
finally:
sys.stdout = _stdout
sys.stderr = _stderr
with log_print(open('mylogfile.log', 'w')):
print('hello world')
print('hello world on stderr', file=sys.stderr)
# you can capture the output to a string with:
# with log_print(io.StringIO()) as log:
# ....
# print('[captured output]', log.getvalue())
edited Sep 5 '18 at 13:41
answered Feb 19 '18 at 16:48
damiodamio
3,41522443
3,41522443
add a comment |
add a comment |
7
That's not really a python thing, it's a shell function. Just run your script like
script.p > file– Falmarri
Jan 13 '11 at 0:52
I currently solve the problem using nohup, but I thought there might be something more clever...
– hayavuk
Jan 13 '11 at 0:59
1
@foxbunny: nohup? Why simply
someprocess | python script.py? Why involvenohup?– S.Lott
Jan 13 '11 at 1:39
3
Rewrite the
printstatements to apply theloggingmodule from the stdlib. Then you can redirect output everywhere, have control over how much output you want etc. In most cases production code should notprintbutlog.– erikbwork
Jan 3 '14 at 7:44
2
Perhaps a better solution for this problem is the screen command, which will save your bash session and allow you to access it from different runs.
– Ryan Amos
May 5 '14 at 23:08