This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: InteractiveInterpreter always prints to stdout
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, graphite, martin.panter, r.david.murray, terry.reedy
Priority: normal Keywords: patch

Created on 2015-07-09 13:00 by graphite, last changed 2022-04-11 14:58 by admin.

Files
File name Uploaded Description Edit
issue24595.diff berker.peksag, 2015-12-10 18:34 review
Messages (7)
msg246487 - (view) Author: graphite (graphite) Date: 2015-07-09 13:00
I have a use-case when I need to forward InteractiveConsole through Unix/TCP socket. Expected implementation:

class InteractiveSocket(InteractiveConsole):
  def __init__(self, socket):
    self._socket = socket
    ...

  def raw_input(...):
    # read from socket

  def write(...):
    # write to socket

However, only syntax errors and tracebacks are written into a socket, while actual output still appears on servers stdout. Digging through it I realized, that the output happens inside exec call in InteractiveInterpreter.runcode and here is why:

>>> c=compile('42', '', 'single')
>>> dis.dis(c)
<<< 1           0 LOAD_CONST               0 (42)
                3 PRINT_EXPR          
                4 LOAD_CONST               1 (None)
                7 RETURN_VALUE

where PRINT_EXPR uses _Py_IDENTIFIER(displayhook);

I ended up with the following dirty hack in my derived class:

def runcode(self, code):
  class OutWriter:
    pass
  writer = OutWriter()
  writer.write = self.write
  old = sys.stdout
  sys.stdout = writer
  try:
    exec(code, self.locals)
  except SystemExit:
    raise
  except:
    self.showtraceback()
  sys.stdout = old

I think it would be nice to make InteractiveInterpreter extendable out of the box, though I don't have exact solution here.
msg246511 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-07-09 17:09
Does it not work to create an unbuffered makefile object from the socket and assign that to stdout?  Regardless, if you need to set it and restore it around runcode you can use super() to call the base class method.

I think providing an easier API to change stdin/stdout/stderr is a reasonable RFE, though.
msg246598 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2015-07-11 08:16
To me, this cries out for a public context manager ( believe there is a public one in test.support, or something), so one can write

with stdout(ob):
  print(stuff)

I am not sure, though, where the C.M.s should live.
msg247976 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-08-04 02:40
Terry: perhaps you’re thinking of <https://docs.python.org/dev/library/contextlib.html#contextlib.redirect_stdout> :)
msg247984 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2015-08-04 05:34
There is also redirect_stderr, but not for stdin.  I am not sure what specific issue is left here, of if this should be closed.
msg256179 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2015-12-10 18:34
I agree with David. I've added a "stream" attribute to InteractiveInterpreter. I don't have a strong preference between a getstream method and a stream attribute(or something different) so I will add documentation changes and tests later.
msg256181 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2015-12-10 20:11
I strongly prefer attribute, as in the patch.
History
Date User Action Args
2022-04-11 14:58:18adminsetgithub: 68783
2015-12-10 20:11:07terry.reedysetmessages: + msg256181
2015-12-10 18:34:02berker.peksagsetfiles: + issue24595.diff

nosy: + berker.peksag
messages: + msg256179

keywords: + patch
stage: patch review
2015-08-04 05:34:53terry.reedysetmessages: + msg247984
2015-08-04 02:40:42martin.pantersetnosy: + martin.panter
messages: + msg247976
2015-07-11 08:16:25terry.reedysetnosy: + terry.reedy
messages: + msg246598
2015-07-09 17:09:44r.david.murraysetversions: + Python 3.6
nosy: + r.david.murray

messages: + msg246511

type: behavior -> enhancement
2015-07-09 13:00:12graphitecreate