Sublime Forum

How to recover lost sys.stdout?

#1

Let’s say i got this test:

import unittest
import sys

print(sys.stdout)
print(sys.stderr)

class StdoutWrapper:

    def __init__(self):
        self.st_stdout = sys.stdout
        self.st_stderr = sys.stderr
        self.clear()

    def start(self):
        sys.stdout = self
        sys.stderr = self

    def stop(self):
        sys.stdout = self.st_stdout
        sys.stderr = self.st_stderr

    def clear(self):
        self.lines = []

    def write(self, txt):
        self.lines.append(txt)

    def value(self):
        return "".join(self.lines)

class TestMcve(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_borg(self):
        x = StdoutWrapper()
        x.start()
        print('THIS TEXT IS GOING TO BE CAPTURES')
        x.stop()

        # THIS TEST SHOULD ALWAYS BE DISPLAYED
        print(x.value())

Now, let’s say I use randy3k unittesting package to test it this way.

As you can see in the video, because of the forced crash I won’t be able to restore the initial sys.stdout/sys.stderr values even if reload the whole package, I kind of understand the reason why this is happening, (plugin life cycle)… so my question would be, how can i grant sys.stdout/sys.stderr will be restored properly to the original sublime._LogWriter objects? Let’s say instead of this object with start/stop methods I create a contextmanager like the one proposed here, would it be possible to restore sys.stdout with the ._LogWriter (i’d expect it to be a Singleton object)

Thanks.

0 Likes

#2

If you feel my previous explanation is just too long, let me simplify it like this, open the ST console and type:

>>> import sys; 
>>> sys.stdout=None
>>> import sublime_api
>>> dir(sublime_api)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
RuntimeError: lost sys.stdout

Ok, the original LogWriter has been lost, how do i restore it at this point using the sublime.API?

0 Likes

#3

The SO post you linked already gives you the answer:

in ST, sys.__stdout__ doesn’t seem to have a value by default, but you can set it to sys.stdout before modifying sys.stdout:

import sys
sys.__stdout__ = sys.stdout
sys.stdout = None

sys.stdout = sys.__stdout__

print(sys.stdout)

<sublime._LogWriter object at 0x000000000300CE80>

1 Like