New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-opening /dev/tty breaks readline #73582
Comments
The following code works on python2 (tested with 2.7.6), but breaks readline for python3 (tested with 3.4.3):
Re-opening /dev/tty as stdin is a very useful technique. For example, one could debug a script that takes a file as stdin by re-opening the stdin as /dev/tty and using pdb.set_trace(). See bug report for python2 in 2002 here: https://bugs.python.org/issue512981 |
I think the difference between Python 2 and 3 here is that Python 2’s file objects, including sys.stdin, wrap C library FILE objects, which is supported by the Readline library. However Python 3 has its own kind of file objects, independent of standard C and Readline. Python 3 only uses Readline if sys.stdin corresponds to the original C stdin FILE object. Perhaps Python 3 could support Readline with other file objects (or at least file descriptors), but I think that would be a new feature. |
So, if I understood correctly, the Is there any workaround to make Maybe this behavior should be documented in the |
I agree it would be good to document when the Readline library is invoked. Yes, the “readline” module is only designed to work with the original sys.stdin and sys.stdout. Python’s “open” function does not use <stdio.h> FILE objects, but Python does use <stdio.h> FILE objects internally for its Readline hook, and passes them to the Readline library. Python falls back to dumber implementations, which may not implement history nor completion, when it decides not to use Readline. The “readline” module is implemented in Modules/readline.c and uses “rl_instream” <https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#IDX228\> and “rl_outstream” to specify <stdio.h> FILE objects that the Readline library uses. These FILE objects are passed through the PyOS_ReadlineFunctionPointer hook <https://docs.python.org/3.4/c-api/veryhigh.html#c.PyOS_ReadlineFunctionPointer\> from the PyOS_Readline function in Parser/myreadline.c. They are required to be terminals (checked with the Posix “isatty” call). The implementation of Python’s “input” function is in the “builtin_input” C function in Python/bltinmodule.c. Before calling PyOS_Readline, it requires that sys.stdin.fileno() and sys.stdout.fileno() match the <stdio.h> stdin and stdout FILE objects. It also does its own isatty checks. You might have some luck calling “fopen” with the “ctypes” module, or writing your own Readline module, but it wouldn’t be straightforward. You might be able to fool the check by reopening file descriptors 0 and 1, but that seems rather hacky. Or you might rely on the OS to provide history and/or completion (I think the Windows console does this in a limited way), or an external Readline wrapper program (e.g. search for “rlwrap”). |
in
and goes on to check So it's really only checking that This construct seems to work to debug cli filters (and retain readline): # save stdin, pdb needs stdio fds itself
if select([sys.stdin], [], [], None)[0]:
inbuf = sys.stdin.read() # todo: problematic with large inputs
os.close(sys.stdin.fileno())
try: sys.stdin = open('/dev/tty')
except: pass # no ctty, but then pdb would not be in use
else:
# non-filter use case, ie open files as "inbuf" I think maybe Python should only check As such, this issue should potentially be reclassified as a bug, not a feature request. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: