infile and outfile parameters for the input function

Previously discussed here [1] [2], it was raised that the input function could take file objects to display prompts in places other than sys.stdout and receive input from places other than sys.stdin. Locally, the patch I have produces the following help text: ``` Help on built-in function input in module builtins: input(prompt=None, /, infile=None, outfile=None) Read a string from a stream, or from standard input by default. The trailing newline is stripped. The output file is standard output by default. The prompt string, if given, is printed to the output file without a trailing newline before reading input. If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError. On *nix systems, readline is used if available. ``` The idea of an errfile parameter was also raised. What do people think about this? [1]: https://mail.python.org/pipermail/python-ideas/2017-September/047230.html [2]: https://mail.python.org/pipermail/python-ideas/2017-September/thread.html#47... Kind regards, Sam Ezeh

On Mon, May 02, 2022 at 05:42:12PM -0000, sam.z.ezeh@gmail.com wrote:
input(prompt=None, /, infile=None, outfile=None)
What do people think about this?
I think I want to see some examples of how and why you would use it, and why one couldn't just use the redirect_stdout context manager. (Plus not-yet-existing, but hopefully soon, redirect_stdin.) Long before we had context managers, I manually redirected stdin and stdout to programmatically feed input and capture output from `raw_input`. It would be nice to be able to do that more easily, but I'm not sure that parameters to the function are better than context managers. -- Steve

Using the prospective redirect_stdin context manager, the following code ``` with open("/dev/tty", 'r+') as file: with contextlib.redirect_stdin(file), contextlib.redirect_stdout(file): name = input('Name: ') print(name) ``` Could be rewritten like this ``` with open('/dev/tty', 'r+') as file: name = input('Name: ', infile=file, outfile=file) print(name) ```

On Mon, May 02, 2022 at 07:55:16PM -0000, sam.z.ezeh@gmail.com wrote:
Thanks for the example, but that doesn't explain the why. Why are we redirecting IO to a tty? Assume your audience is not made up of expert Linux sys admins who even know what a tty is :-) (I know what a tty is, kinda, but I still don't know what the above does.) -- Steve

On Tue, 3 May 2022 at 11:14, Steven D'Aprano <steve@pearwood.info> wrote:
I can explain a bit of the why, although the most common use case is already covered by the getpass module. If your stdio streams are redirected, and you need to get some information from the user, opening the tty explicitly lets you do that. For example, let's say you run a command like "spam | ssh user@host | ham", and the ssh command needs to get credentials from you; it'll open /dev/tty, write a prompt to it, read a password from it, and then close it. But as mentioned, the obvious case of querying the user for credentials is much better handled by simply calling getpass (which has different handling on Windows, for instance). I'm sure there are other use cases for "write one prompt to tty, then read one line", but honestly, I would be fine with leaving input() as it is, and just using the context manager, since it would allow you to print multiple lines as well as reading a command. ChrisA

On Tue, 3 May 2022 at 17:28, Serhiy Storchaka <storchaka@gmail.com> wrote:
At the very least, I would expect the write to be flushed before the read happens (which wouldn't necessarily be the default when the newline is omitted, as in this case); and depending on configuration, something like GNU Readline might be active when calling input() that wouldn't be active when simply reading a line from an arbitrary file descriptor. ChrisA

On Mon, May 02, 2022 at 05:42:12PM -0000, sam.z.ezeh@gmail.com wrote:
input(prompt=None, /, infile=None, outfile=None)
What do people think about this?
I think I want to see some examples of how and why you would use it, and why one couldn't just use the redirect_stdout context manager. (Plus not-yet-existing, but hopefully soon, redirect_stdin.) Long before we had context managers, I manually redirected stdin and stdout to programmatically feed input and capture output from `raw_input`. It would be nice to be able to do that more easily, but I'm not sure that parameters to the function are better than context managers. -- Steve

Using the prospective redirect_stdin context manager, the following code ``` with open("/dev/tty", 'r+') as file: with contextlib.redirect_stdin(file), contextlib.redirect_stdout(file): name = input('Name: ') print(name) ``` Could be rewritten like this ``` with open('/dev/tty', 'r+') as file: name = input('Name: ', infile=file, outfile=file) print(name) ```

On Mon, May 02, 2022 at 07:55:16PM -0000, sam.z.ezeh@gmail.com wrote:
Thanks for the example, but that doesn't explain the why. Why are we redirecting IO to a tty? Assume your audience is not made up of expert Linux sys admins who even know what a tty is :-) (I know what a tty is, kinda, but I still don't know what the above does.) -- Steve

On Tue, 3 May 2022 at 11:14, Steven D'Aprano <steve@pearwood.info> wrote:
I can explain a bit of the why, although the most common use case is already covered by the getpass module. If your stdio streams are redirected, and you need to get some information from the user, opening the tty explicitly lets you do that. For example, let's say you run a command like "spam | ssh user@host | ham", and the ssh command needs to get credentials from you; it'll open /dev/tty, write a prompt to it, read a password from it, and then close it. But as mentioned, the obvious case of querying the user for credentials is much better handled by simply calling getpass (which has different handling on Windows, for instance). I'm sure there are other use cases for "write one prompt to tty, then read one line", but honestly, I would be fine with leaving input() as it is, and just using the context manager, since it would allow you to print multiple lines as well as reading a command. ChrisA

On Tue, 3 May 2022 at 17:28, Serhiy Storchaka <storchaka@gmail.com> wrote:
At the very least, I would expect the write to be flushed before the read happens (which wouldn't necessarily be the default when the newline is omitted, as in this case); and depending on configuration, something like GNU Readline might be active when calling input() that wouldn't be active when simply reading a line from an arbitrary file descriptor. ChrisA
participants (4)
-
Chris Angelico
-
sam.z.ezeh@gmail.com
-
Serhiy Storchaka
-
Steven D'Aprano