8

I am using the readline module with Python 2.7.3 with Fedora 17. I do not have this problem with Ubuntu 12.10.

During import readline, an escape char is displayed.

$ python -c 'import readline' |less
ESC[?1034h(END)

Usually when I get unexpected output like this, I handle it using stdout/stderr redirection to a dummy file descriptor (example below). But this time, this method does not work.

import sys

class DummyOutput(object):
    def write(self, string):
        pass

class suppress_output(object):
    """Context suppressing stdout/stderr output.
    """
    def __init__(self):
        pass
    def __enter__(self):
        sys.stdout = DummyOutput()
        sys.stderr = DummyOutput()
    def __exit__(self, *_):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

if __name__ == '__main__':
    print 'Begin'
    with suppress_output():
        # Those two print statements have no effect
        # but *import readline* prints an escape char
        print 'Before importing'
        import readline
        print 'After importing'
    # This one will be displayed
    print 'End'

If you run this snippet in a test.py script, you will see that inside the suppress_output context, the print statements are indeed suppressed, but not the escape char.

$ python test.py |less
Begin
ESC[?1034hEnd
(END)

So here are my two questions:

  1. How is it possible for this escape character to get through?
  2. How to suppress it?
Alex
  • 181
  • 1
  • 4
  • 1
    Looks like the module wants to change the terminal state with an escape sequence but that doesn't work. You shouldn't try to work around that, fix that instead. – wRAR Apr 02 '13 at 09:36
  • Yes, there is a workaround based on that here http://reinout.vanrees.org/weblog/2009/08/14/readline-invisible-character-hack.html. But this did not answer my first question :) (and I was afraid that was not very portable, but I may be wrong). – Alex Apr 02 '13 at 09:49
  • I suspect your terminal and/or terminfo DB cause this problem. – wRAR Apr 02 '13 at 09:51
  • I think the file descriptor for stdout is always 1. so you can access it directly with for example os. – User Apr 02 '13 at 11:04
  • 1
    I have this problem when ssh-ing to a RedHat machine from my MacBook, and `TERM=xterm-256color`. I believe it's a readline setup bug. Best I can do for now is work around it with `export TERM=vt100`. – Paul Price Jun 04 '13 at 21:03
  • 1
    related python bug http://bugs.python.org/issue19884 – jfs May 12 '14 at 18:09

3 Answers3

1

here is what I'm using (admittedly based on @jypeter 's answer), clearing the TERM environment variable only if the output does not go to a tty (e.g. is being redirected to a file):

if not sys.stdout.isatty():

    # remember the original setting
    oldTerm = os.environ['TERM']

    os.environ['TERM'] = ''

    import readline

    # restore the orignal TERM setting
    os.environ['TERM'] = oldTerm

    del oldTerm
Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
0

To answer the first question: changing sys.stdout doesn't actually affect what file stdout's file descriptor is pointing at, but instead just what high-level file object Python considers to be stdout. Said another way, changing sys.stdout affects your Python code, but not (generally) any compiled extensions you may be using (like the readline module). All this applies to sys.stderr as well.

To answer the second: you can do what this answer suggests (which should be straightforward to port to Python). Though the suggestions in the comments sound like a better way to go.

Community
  • 1
  • 1
johncs
  • 163
  • 2
  • 8
  • here's [how to redirect stdout at C level in Python](http://stackoverflow.com/a/22434262/4279) – jfs Aug 04 '15 at 04:17
0

I have used the following hack, before importing readline

import os
if os.environ['TERM'] == 'xterm':
    os.environ['TERM'] = 'vt100'
# Now it's OK to import readline :)
import readline
  • 1
    the problem appears also with `xterm-256color` – Andre Holzner Jul 31 '15 at 11:12
  • but setting `os.environ['TERM'] = ''` then importing `readline` and then restore `os.environ['TERM']` back to what it was before avoids printing the escape sequence (not sure about other functionality of `readline` though...) – Andre Holzner Jul 31 '15 at 13:02