import pydevd_constants #@UnusedImport -- defines False and True if not there. IS_PY3K = pydevd_constants.IS_PY3K class IORedirector: '''This class works to redirect the write function to many streams ''' def __init__(self, *args): self._redirectTo = args def write(self, s): for r in self._redirectTo: try: r.write(s) except: pass def isatty(self): return False def flush(self): for r in self._redirectTo: r.flush() def __getattr__(self, name): for r in self._redirectTo: if hasattr(r, name): return r.__getattribute__(name) raise AttributeError(name) class IOBuf: '''This class works as a replacement for stdio and stderr. It is a buffer and when its contents are requested, it will erase what it has so far so that the next return will not return the same contents again. ''' def __init__(self): self.buflist = [] import os self.encoding = os.environ.get('PYTHONIOENCODING', 'utf-8') def getvalue(self): b = self.buflist self.buflist = [] #clear it return ''.join(b) def write(self, s): if not IS_PY3K: if isinstance(s, unicode): s = s.encode(self.encoding) self.buflist.append(s) def isatty(self): return False def flush(self): pass class _RedirectionsHolder: _stack_stdout = [] _stack_stderr = [] def StartRedirect(keep_original_redirection=False, std='stdout'): ''' @param std: 'stdout', 'stderr', or 'both' ''' import sys buf = IOBuf() if std == 'both': config_stds = ['stdout', 'stderr'] else: config_stds = [std] for std in config_stds: original = getattr(sys, std) stack = getattr(_RedirectionsHolder, '_stack_%s' % std) stack.append(original) if keep_original_redirection: setattr(sys, std, IORedirector(buf, getattr(sys, std))) else: setattr(sys, std, buf) return buf def EndRedirect(std='stdout'): import sys if std == 'both': config_stds = ['stdout', 'stderr'] else: config_stds = [std] for std in config_stds: stack = getattr(_RedirectionsHolder, '_stack_%s' % std) setattr(sys, std, stack.pop())