The difference between sys.stdout.write and print?
print
is just a thin wrapper that formats the inputs (modifiable, but by default with a space between args and newline at the end) and calls the write function of a given object. By default this object is sys.stdout
, but you can pass a file using the "chevron" form. For example:
print >> open('file.txt', 'w'), 'Hello', 'World', 2+3
See: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement
In Python 3.x, print
becomes a function, but it is still possible to pass something other than sys.stdout
thanks to the file
argument.
print('Hello', 'World', 2+3, file=open('file.txt', 'w'))
See https://docs.python.org/3/library/functions.html#print
In Python 2.6+, print
is still a statement, but it can be used as a function with
from __future__ import print_function
Update: Bakuriu commented to point out that there is a small difference between the print function and the print statement (and more generally between a function and a statement).
In case of an error when evaluating arguments:
print "something", 1/0, "other" #prints only something because 1/0 raise an Exception
print("something", 1/0, "other") #doesn't print anything. The function is not called
print() vs sys.stdout.write(): which and why?
"Can someone please explain (or direct me to an existing explanation) the differences between print() and sys.stdout.write, the cases in which each should be used and the rational for those conventions?"
Well I guess the silence you hear regarding Python3's print() function, is because there practically is only one difference: Usage. Let me quote PEP-3105: [1]
The signature for print()
is:
def print(*args, sep=' ', end='\n', file=None)
A call like:
print(a, b, c, file=sys.stderr)
will be equivalent to today's:
print >>sys.stderr, a, b, c
while the optional sep and end arguments specify what is printed between and after the arguments, respectively.
The softspace feature (a semi-secret attribute on files currently used to tell print whether to insert a space before the first item) will be removed. Therefore, there will not be a direct translation for today's:
print "a", print
which will not print a space between the "a" and the newline.
So, quoting Guido van Rossum's discussion of the problem in 2005 [1]: There is a distinct non-linearity in print's ease of use once you decide that you don't want to have spaces between items; you either have to switch to using sys.stdout.write()
, or you have to collect all items in a string. This is not a simple transformation, consider what it takes to get rid of the spaces before the commas in this simple example:
print "x =", x, ", y =", y, ", z =", z
If it was a built-in function, having a built-in companion function that did a similar thing without inserting spaces and adding a newline would be the logical thing to do (or adding keyword parameters to control that behavior; but I prefer a second function); but with only
print as it currently stands, you'd have to switch to something like
print "x = " + str(x) + ", y = " + str(x) + ", z = " + str(z)
or
print "x = %s, y = %s, z = %s" % (x, y, z)
neither of which is very attractive. (And don't tell me that the spaces are no big deal -- they aren't in this example, but they are in other situations.)
Good question for a sunday morning down memory lane; Why this apparent redundancy? Because it is pythonically more correct to write higher-level code:
7th Zen of python: "Readability counts"
Difference between sys.stdout.write and print when printing variables
The return value for sys.stdout.write()
returns the no. of bytes written. In this case 1
which also gets printed on the interactive interpret prompt for any expressions entered.
Example:
>>> import sys
>>> sys.stdout.write("foo")
foo3
If you wanted to hide this you could do this:
>>> nbytes = sys.stdout.write("foo\n")
foo
sys.stdout.write() Acting different in interactive mode
12
is the return value of write
, i.e. the number of characters written. which in interactive mode is printed out, followed by a line feed
to fix this you could either indicate to the interpreter that you're not interested in this value (e.g. using _ = stdout.write(s)
) or you could put everything into a function and hence keep it away from the REPL
I'd suggest doing the latter, e.g. something like:
def looper(n):
for i in range(n):
sys.stdout.write("\r Loading: {}".format(i))
sys.stdout.flush()
time.sleep(0.5)
sys.stdout.write("\n")
then invoke as looper(10)
python unicode handling differences between print and sys.stdout.write
This is due to a long-standing bug that was fixed in python-2.7, but too late to be back-ported to python-2.6.
The documentation states that when unicode strings are written to a file, they should be converted to byte strings using file.encoding. But this was not being honoured by sys.stdout, which instead was using the default unicode encoding. This is usually set to "ascii" by the site module, but it can be changed with sys.setdefaultencoding:
Python 2.6.7 (r267:88850, Aug 14 2011, 12:32:40) [GCC 4.6.2] on linux3
>>> a = u'\xa6\n'
>>> sys.stdout.write(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec cant encode character u'\xa6' ...
>>> reload(sys).setdefaultencoding('utf8')
>>> sys.stdout.write(a)
¦
However, a better solution might be to replace sys.stdout with a wrapper:
class StdOut(object):
def write(self, string):
if isinstance(string, unicode):
string = string.encode(sys.__stdout__.encoding)
sys.__stdout__.write(string)
>>> sys.stdout = StdOut()
>>> sys.stdout.write(a)
¦
Why is sys.stdout.write called twice?
Your perceived results indicates that print()
calls file.write
twice: Once for the data and once for the "end content", which is a newline by default and can be overridden with the end
keyword argument. Relevant source code lines confirm this speculation.
However, this is not something you should rely on. It's entirely implementation details, may be different for another implementation (e.g. PyPy) and may change at any time without notice, not to mention that overriding builtins is another bad practice. You should avoid this kind of practice without a compelling reason not to modify other parts of the code to use your custom logging facility.
Should you really need to do monkey-patching, it's safer to override the print()
function since it has a defined, reliable interface. You can import the builtins
module and assign your new print function to builtins.print
, maintaining control over calls to your logging handler.
Is there a function to print w/o newline that is not sys.stdout.write or print(,end=)?
You're using the IDLE shell to run your program, don't.
IDLE poorly manages outputting text and does slow down when outputting extremely long lines of it (this is the reason why print
without the end
keyword argument works alright, because you're printing multiple separate lines, not 1 line which is getting increasingly longer).
Instead just use the standard Windows command line (cmd.exe).
You can do this (assuming your installation has been configured correctly) by either running your .py file via the GUI or by running:
python filename.py
in the command line.
This has been reported as a bug in Python (IDLE shell window gets very slow when displaying long lines) back in 2006 and the issue is still open.
You can read more including some numbers on this Stack Overflow post.
Related Topics
If Monkey Patching Is Permitted in Both Ruby and Python, Why Is It More Controversial in Ruby
Programmatically Extract Data from an Excel Spreadsheet
How to Overcome Typeerror: Unhashable Type: 'List'
How to Round a Floating Point Number Up to a Certain Decimal Place
Swift If Or/And Statement Like Python
Typeerror: Can't Use a String Pattern on a Bytes-Like Object in Re.Findall()
How to Replace Only Part of the Match with Python Re.Sub
How to Fetch a Non-Ascii Url with Urlopen
Is Python's Sorted() Function Guaranteed to Be Stable
Why Can't Python Find Shared Objects That Are in Directories in Sys.Path
How to Link Pycharm with Pyspark
Difference Between Multiple If's and Elif'S
MAC Osx Python Ssl.Sslerror: [Ssl: Certificate_Verify_Failed] Certificate Verify Failed (_Ssl.C:749)
Python - Use List as Function Parameters
Convert Column to Date Format (Pandas Dataframe)
I Don't Understand This Python _Del_ Behaviour
What's an Efficient Way to Find If a Point Lies in the Convex Hull of a Point Cloud