Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (revision 58477) +++ Python/pythonrun.c (working copy) @@ -51,6 +51,7 @@ /* Forward */ static void initmain(void); static void initsite(void); +static int initstdio(void); static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, PyCompilerFlags *, PyArena *); static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, @@ -241,8 +242,12 @@ initsigs(); /* Signal handling stuff, including initintr() */ initmain(); /* Module __main__ */ + if (initstdio() < 0) + Py_FatalError("Py_Initialize: can't initialize sys standard" + "streams"); if (!Py_NoSiteFlag) initsite(); /* Module site */ + /* auto-thread-state API, if available */ #ifdef WITH_THREAD @@ -676,6 +681,103 @@ } } +/* Initialize sys.stdin, stdout, stderr and __builtins__.open */ +static int +initstdio(void) +{ + PyObject *iomod=NULL, *open, *wrapper; + PyObject *bimod=NULL; + PyObject *m; + PyObject *std=NULL, *args=NULL, *kwargs=NULL; + int status = 0; + + /* Hack to avoid a nasty recursion issue when Python is invoked + in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ + if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) { + goto error; + } + Py_DECREF(m); + + if (!(m = PyImport_ImportModule("encodings.latin_1"))) { + goto error; + } + Py_DECREF(m); + + if (!(bimod = PyImport_ImportModule("__builtin__"))) { + goto error; + } + + if (!(iomod = PyImport_ImportModule("io"))) { + goto error; + } + if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) { + goto error; + } + if (!(open = PyObject_GetAttrString(iomod, "open"))) { + goto error; + } + + if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) { + goto error; + } + + /* Add __builtin__.open */ + if (!(kwargs = PyDict_New())) { + goto error; + } + if (PyDict_SetItemString(kwargs, "newline", PyString_FromString("\n")) + == -1) { + goto error; + } + + /* Set sys.stdin */ + if (!(args = Py_BuildValue("(is)", 0, "r"))) { + goto error; + } + if (!(std = PyObject_Call(open, args, kwargs))) { + goto error; + } + PySys_SetObject("__stdin__", std); + PySys_SetObject("stdin", std); + Py_DECREF(std); + Py_DECREF(args); + + /* Set sys.stdout */ + if (!(args = Py_BuildValue("(is)", 1, "w"))) { + goto error; + } + if (!(std = PyObject_Call(open, args, kwargs))) { + goto error; + } + PySys_SetObject("__stdout__", std); + PySys_SetObject("stdout", std); + Py_DECREF(std); + Py_DECREF(args); + + /* Set sys.stderr */ + if (!(args = Py_BuildValue("(is)", 2, "w"))) { + goto error; + } + if (!(std = PyObject_Call(open, args, kwargs))) { + goto error; + } + PySys_SetObject("__stderr__", std); + PySys_SetObject("stderr", std); + Py_DECREF(std); + Py_DECREF(args); + + goto finally; + +error: + status = -1; + Py_XDECREF(args); +finally: + Py_XDECREF(kwargs); + Py_XDECREF(bimod); + Py_XDECREF(iomod); + return status; +} + /* Parse input from a file and execute it */ int @@ -1146,10 +1248,10 @@ int err = 0; PyObject *f = PySys_GetObject("stderr"); Py_INCREF(value); - if (f == NULL) + if (f == NULL) { _PyObject_Dump(value); - if (f == NULL) fprintf(stderr, "lost sys.stderr\n"); + } else { fflush(stdout); if (tb && tb != Py_None) @@ -1589,6 +1691,9 @@ Py_FatalError(const char *msg) { fprintf(stderr, "Fatal Python error: %s\n", msg); + if (PyErr_Occurred()) { + PyErr_Print(); + } #ifdef MS_WINDOWS OutputDebugString("Fatal Python error: "); OutputDebugString(msg); Index: Lib/site.py =================================================================== --- Lib/site.py (revision 58477) +++ Lib/site.py (working copy) @@ -402,23 +402,6 @@ (err.__class__.__name__, err)) -def installnewio(): - """Install new I/O library as default.""" - import io - # Hack to avoid a nasty recursion issue when Python is invoked - # in verbose mode: pre-import the Latin-1 and UTF-8 codecs - from encodings import latin_1, utf_8 - # Trick so that open won't become a bound method when stored - # as a class variable (as dumbdbm does) - class open: - def __new__(cls, *args, **kwds): - return io.open(*args, **kwds) - __builtin__.open = open - sys.__stdin__ = sys.stdin = io.open(0, "r", newline='\n') - sys.__stdout__ = sys.stdout = io.open(1, "w", newline='\n') - sys.__stderr__ = sys.stderr = io.open(2, "w", newline='\n') - - def main(): abs__file__() paths_in_sys = removeduppaths() @@ -433,7 +416,6 @@ sethelper() aliasmbcs() setencoding() - installnewio() execsitecustomize() # Remove sys.setdefaultencoding() so that users cannot change the # encoding after initialization. The test for presence is needed when Index: Lib/io.py =================================================================== --- Lib/io.py (revision 58477) +++ Lib/io.py (working copy) @@ -178,6 +178,16 @@ return text +class OpenWrapper: + """Wrapper for __builtin__.open + + Trick so that open won't become a bound method when stored + as a class variable (as dumbdbm does) + """ + def __new__(cls, *args, **kwargs): + return open(*args, **kwargs) + + class UnsupportedOperation(ValueError, IOError): pass