[Python-ideas] allow overriding files used for the input builtin

Steven D'Aprano steve at pearwood.info
Fri Sep 29 06:25:04 EDT 2017


On Fri, Sep 29, 2017 at 05:53:58AM +0000, Wren Turkal wrote:

[...]
> The basic idea is to add fin, fout, and ferr file object parameters 
> and default to using what is used today when the args are not 
> specified. I believe this would be useful to allow captures input and 
> send output to specific files when using input. The input builtin has 
> some logic to use readline if it's available. It would be nice to be 
> able to use this same logic no matter what files are being used for 
> input/output.


I've done the whole "set stdout and stdin, call input, reset stdout and 
stdin" dance, and so I like this concept of being able to easily use 
input() non-interactively. I think your basic idea is a good one.

I wonder what you think the ferr parameter will do? As far as I know, 
input() doesn't use stderr.

I also don't think much of your parameter names. They strike me as very 
C-like, rather than Pythonic.

So my proposal is:

input(prompt, *, infile, outfile)

where infile must be a file-like object with a read() method, suitable 
for replacing stdin, and outfile must be a file-like object with a 
write() method suitable for replacing stdout.


> This is meant to turn code like the following:
> 
> orig_stdin = sys.stdin
> orig_stdout = sys.stdout
> with open('/dev/tty', 'r+') as f:
>     sys.stdin = f
>     sys.stdout = f
>     name = input('Name? ')
> 
> sys.stdin = orig_stdin
> sys.stdout = orig_stdout
> print(name)

For production use, that should be wrapped in a try...finally:


try:
   ...
finally:
    sys.stdin = orig_stdin
    sys.stdout = orig_stdout


> into something more like this:
> 
> with open('/dev/tty', 'r+') as f:
>     name = input('Name? ', fin=f, fout=f)
> 
> print(name)

I like it very much.

But as an alternative, perhaps all we really need is a context manager 
to set the std* files:

with open('/dev/tty', 'r+') as f:
    with stdio(stdin=f, stdout=f):
        name = input('Name? ')

print(name)


That's nearly as nice, and is possibly useful in more situations. Or 
maybe we should have both?


[...]
> Would love to see if anyone else is interested in this. I think it's 
> pretty cool that the core logic really didn't need to be changed other 
> than plumbing in the new args.

Definitely interested!



-- 
Steve


More information about the Python-ideas mailing list