diff --git a/Lib/code.py b/Lib/code.py --- a/Lib/code.py +++ b/Lib/code.py @@ -1,15 +1,15 @@ """Utilities needed to emulate Python's interactive interpreter. """ # Inspired by similar code by Jeff Epler and Fredrik Lundh. - +import contextlib import sys import traceback import argparse from codeop import CommandCompiler, compile_command __all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", "compile_command"] @@ -17,16 +17,18 @@ class InteractiveInterpreter: """Base class for InteractiveConsole. This class deals with parsing and interpreter state (the user's namespace); it doesn't deal with input buffering or prompting or input file naming (the filename is always passed in explicitly). """ + stream = sys.stderr + def __init__(self, locals=None): """Constructor. The optional 'locals' argument specifies the dictionary in which code will be executed; it defaults to a newly created dictionary with key "__name__" set to "__console__" and key "__doc__" set to None. @@ -83,17 +85,18 @@ class InteractiveInterpreter: SystemExit, which is reraised. A note about KeyboardInterrupt: this exception may occur elsewhere in this code, and may not always be caught. The caller should be prepared to deal with it. """ try: - exec(code, self.locals) + with contextlib.redirect_stdout(self.stream): + exec(code, self.locals) except SystemExit: raise except: self.showtraceback() def showsyntaxerror(self, filename=None): """Display the syntax error that just occurred. @@ -152,17 +155,17 @@ class InteractiveInterpreter: def write(self, data): """Write a string. The base implementation writes to sys.stderr; a subclass may replace this with a different implementation. """ - sys.stderr.write(data) + self.stream.write(data) class InteractiveConsole(InteractiveInterpreter): """Closely emulate the behavior of the interactive Python interpreter. This class builds on InteractiveInterpreter and adds prompting using the familiar sys.ps1 and sys.ps2, and input buffering.