5

I was looking at the Python documentation for print which states:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

As it can be seen, if the file on which to print is not specified, the default sys.stdout is used, which got me thinking.

Calling print definitely does not import sys in the background, so how does it work?

is sys.stdout somehow reachable from everywhere?


Example:

I am using PyCharm and I want to create a function that either prints a message text to a file or to standard output. I began writing:

def my_print(text, file=None):
    print(text, file=file if file is not None else ?)

So what goes after else? sys.stdout does not work and obviously, I am not interested in the verbose:

def my_print(text, file=None):
    if file is None:
        print(text)
    else:
        print(text, file=file)
Ma0
  • 15,057
  • 4
  • 35
  • 65
  • No, neither of those things. That default is in the *definition* of print, not in the place where you use it. – Daniel Roseman Dec 04 '18 at 13:45
  • 1
    @DanielRoseman Thank you for the quick comment. Could you elaborate a bit on that? Maybe with an answer even? – Ma0 Dec 04 '18 at 13:47

2 Answers2

1

The other answer points out that print is implemented in C. However, even if it was implemented in Python, that would not mean that sys was available from everywhere.

Consider this code:

utils.py

import sys

def my_print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False):
    file.write(sep.join(objects))

main.py

from utils import print

my_print('foo')

Here sys is only available within utils, but print will still output to sys.stdout without it being accessible from main.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • so on the `utils.py` the `import sys` **must** be there. – Ma0 Dec 04 '18 at 14:27
  • 1
    Further, it is even possible (but unlikely) to implement as `def my_print(text): import sys; sys.stdout...` where `sys` will not exist anywhere outside of the local scope. – r.ook Dec 04 '18 at 14:54
0

I think @DanielRoseman gave a good idea of why the implementation might not necessarily give you access to sys directly, but to address the last part of your question, you can use this approach...:

def my_print(text, file=None):
    print(text, **({'file': file} if file else {}))

... where basically you are unpacking the argument file=file if file is present, otherwise pass no argument.

In terms of readability I think your original implementation is superior however.


Actually you can just pass None:

def my_print(text, file=None):
    print(text, file=file)

... and it would just print the text if file is not provided...

r.ook
  • 13,466
  • 2
  • 22
  • 39