Skip to content

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

@juliangilbey

Description

@juliangilbey

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.]

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation in the Doc direasy

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions