Reputation: 10740
I have a script that runs automatically on server through cronjob and it import and run several other scripts.
Some of them use prints, which naturally creates IOError: [Errno 5] Input/output error
because the script runs without any SSH / terminal connected, so there's no proper stdout setup.
There are lots of questions about this subject but I couldn't find anyone that actually solve it, assuming I can't remove the print or change the executed scripts.
I tried several things, including:
class StdOut(object):
def __init__(self):
pass
def write(self, string):
pass
sys.stdout = StdOut()
sys.stderr = StdOut()
and
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
pass
__builtin__.print = print
But none of it works. I assume it only affect the module itself and not the modules I import / run later.
So how can I create a stub stdout that will affect all modules in the process? Like I said, I don't want to change the scripts that are executed from the main module, but I can change everything inside the importing module. And just to clearify - everything is imported, no new processes are spawned etc.
Thanks,
Upvotes: 17
Views: 25863
Reputation: 488453
Modifying the builtin or changing sys.stdout
should work (except for subprocesses—but you ruled those out) as long as you do it early enough. If not, though, there's a lower level trick that's much easier:
run your python scripts with I/O redirection that discards output:
python foo.py >/dev/null 2>&1
(assuming Unix-y scripts, as implied by "cron" in the question)
or, redirect file descriptors 1 and 2 (same idea as above, but done within your Python startup rather than as part of the cron-invoked command):
import os
fd = os.open(os.devnull, os.O_RDWR)
# NB: even if stdin is closed, fd >= 0
os.dup2(fd, 1)
os.dup2(fd, 2)
if fd > 2:
os.close(fd)
(this particular bit of code has the side effect of making /dev/null act as stdin, if all descriptors were closed). [Edit: I started with with open(...)
and then switched to os.open
and did not test the final version. Fixed now.]
All that said, a good cron really should have stdout and stderr connected somewhere, and should email the output/error-output to you. Not all cron versions are this nice though.
Upvotes: 13