Search code examples
pythonpython-3.xcpythonpython-internals

RuntimeError: lost sys.stdout


I was trying to debug an issue with abc.ABCMeta - in particular a subclass check that didn't work as expected and I wanted to start by simply adding a print to the __subclasscheck__ method (I know there are better ways to debug code, but pretend for the sake of this question that there's no alternative). However when starting Python afterwards Python crashes (like a segmentation fault) and I get this exception:

Fatal Python error: Py_Initialize: can't initialize sys standard streams
Traceback (most recent call last):
  File "C:\...\lib\io.py", line 84, in <module>
  File "C:\...\lib\abc.py", line 158, in register
  File "C:\...\lib\abc.py", line 196, in __subclasscheck__
RuntimeError: lost sys.stdout

So it probebly wasn't a good idea to put the print in there. But where exactly does the exception come from? I only changed Python code, that shouldn't crash, right?

Does someone know where this exception is coming from and if/how I can avoid it but still put a print in the abc.ABCMeta.__subclasscheck__ method?

I'm using Windows 10, Python-3.5 (just in case it might be important).


Solution

  • This exception stems from the fact that CPython imports io, and, indirectly, abc.py during the initialization of the standard streams:

    if (!(iomod = PyImport_ImportModule("io"))) {
        goto error;
    }
    

    io imports the abc module and registers FileIO as a virtual subclass of RawIOBase, a couple of other classes for BufferedIOBase and others for TextIOBase. ABCMeta.register invokes __subclasscheck__ in the process.

    As you understand, using print in __subclasscheck__ when sys.stdout isn't set-up is a big no-no; the initialization fails and you get back your error:

    if (initstdio() < 0)
        Py_FatalError(
            "Py_NewInterpreter: can't initialize sys standard streams");
    

    You can get around it by guarding it with a hasattr(sys, 'stdout'), sys has been initialized by this point while stdout hasn't (and, as such, won't exist in sys in the early initialization phase):

    if hasattr(sys, 'stdout'):
        print("Debug")
    

    you should get good amount of output when firing Python up now.