Skip to content

The documentation for the print() builtin should perhaps say file=None as default #94286

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

Closed
juliangilbey opened this issue Jun 26, 2022 · 2 comments · Fixed by #94297
Closed
Labels
docs Documentation in the Doc dir easy

Comments

@juliangilbey
Copy link
Contributor

juliangilbey commented Jun 26, 2022

Documentation

The current function definition for the print() builtin at https://docs.python.org/3/library/functions.html#print reads:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

However, this suggests that the default value of file is the original version of sys.stdout at Python iniitialise time, not the current value of sys.stdout at the time the function is called. I just stumbled across a package which does this (function body stripped down to the bare minimum to highlight the issue):

def myfunc(arg1, stream=sys.stdout):
    print(arg1, file=stream)

This looks fine, but it conceals a subtle issue, which is revealed when the function is called like this:

with contextlib.redirect_stdout(sys.stderr):
    myfunc("message")

Since contextlib.redirect_stdout redefines sys.stdout, but in myfunc, the default value of stream is the value of sys.stdout at function definition time, so this snippet still sends the output "message" to sys.stdout rather than sys.stderr.

However, print() does not do this: print looks up the current value of sys.stdout every time it is called without file=... specified. It instead behaves like the following corrected version of myfunc:

def myfunc(arg1, stream=None):
    if stream is None:
        stream = sys.stdout
    print(arg1, file=stream)

My suggestion, therefore, would be to modify the definition given to read:
print(*objects, sep=' ', end='\n', file=None, flush=False)

Most readers will be unaffected by the change, especially as the behaviour of the function when file=None is specified is explicitly described in the second paragraph. But it hints that the best way to specify a default of sys.stdout in a function is to have the default being None and to assign sys.stdout in the body of the function.

[Edit: fix name of contextlib function.]

@ddurgoji
Copy link

I recently started working towards becoming python core developer. I came across this issue marked as easy. Can I take up and fix this issue?

@howiezhao
Copy link
Contributor

I recently started working towards becoming python core developer. I came across this issue marked as easy. Can I take up and fix this issue?

@ddurgoji This issue already has a corresponding PR, refer to the above

miss-islington pushed a commit to miss-islington/cpython that referenced this issue Nov 6, 2022
(cherry picked from commit 2db55e0)

Co-authored-by: Nouran Ali <nouranalimohammed@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Nov 6, 2022
(cherry picked from commit 2db55e0)

Co-authored-by: Nouran Ali <nouranalimohammed@gmail.com>
miss-islington added a commit that referenced this issue Nov 6, 2022
(cherry picked from commit 2db55e0)

Co-authored-by: Nouran Ali <nouranalimohammed@gmail.com>
miss-islington added a commit that referenced this issue Nov 6, 2022
(cherry picked from commit 2db55e0)

Co-authored-by: Nouran Ali <nouranalimohammed@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir easy
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants