Discussion:
sys.stdout and Python3
(too old to reply)
Frank Millman
2013-11-23 13:26:04 UTC
Permalink
Hi all

I have a question arising from another thread, but on a different topic,
hence the new thread.

Under Python2, if you want to print a series of dots to the screen without a
newline, you can do the following:

for i in range(10):
sys.stdout.write('.')
sys.stdout.flush()
time.sleep(1)
sys.stdout.write('\n')

I tried it under Python3, and found that it differs in two ways -

1. Each 'write' is terminated by a newline
2. Each 'write' appends the length of the string written.

So instead of -
..........
I get -
.1
.1
etc

I found that the new 'print' function has a 'flush' argument, so it can now
be written as -

for i in range(10):
print('.', end='', flush=False)
time.sleep(1)
print()

I tried to read the docs on sys.stdout, and I see a lot of changes in this
area, but I could not see the reason for the above behaviour.

Is there a way to reproduce the Python2 behaviour in Python3 using
sys.stdout?

Thanks

Frank Millman
Chris Angelico
2013-11-23 14:16:18 UTC
Permalink
Post by Frank Millman
sys.stdout.write('.')
sys.stdout.flush()
time.sleep(1)
sys.stdout.write('\n')
I tried it under Python3, and found that it differs in two ways -
1. Each 'write' is terminated by a newline
2. Each 'write' appends the length of the string written.
Only in the interactive interpreter, where return values get printed.
In a script, that won't happen. To prevent that from happening
interactively, just assign the result to something:

for i in range(10):
_=sys.stdout.write(".")
sys.stdout.flush()

There definitely is a difference between Py2 and Py3 there, but it's
nothing to do with sys.stdout - it's a change in the REPL (interactive
interpreter, Read/Eval/Print Loop) and how it handles return values
inside loops. I think it's an improvement, overall, though it is a
little confusing when you work with partial output.

ChrisA
Steven D'Aprano
2013-11-24 14:31:48 UTC
Permalink
Post by Frank Millman
sys.stdout.write('.')
sys.stdout.flush()
time.sleep(1)
sys.stdout.write('\n')
I tried it under Python3, and found that it differs in two ways -
1. Each 'write' is terminated by a newline 2. Each 'write' appends the
length of the string written.
Only in the interactive interpreter, where return values get printed. In
a script, that won't happen. To prevent that from happening
_=sys.stdout.write(".")
sys.stdout.flush()
There definitely is a difference between Py2 and Py3 there, but it's
nothing to do with sys.stdout - it's a change in the REPL (interactive
interpreter, Read/Eval/Print Loop) and how it handles return values
inside loops. I think it's an improvement, overall, though it is a
little confusing when you work with partial output.
I don't think the REPL handles return values inside loops any different
from how it handles them outside loops. The difference is that file.write
methods used to return None in Python 2, in Python 3 they return the
number of bytes written.
--
Steven
Chris Angelico
2013-11-24 14:39:41 UTC
Permalink
On Mon, Nov 25, 2013 at 1:31 AM, Steven D'Aprano
Post by Steven D'Aprano
I don't think the REPL handles return values inside loops any different
from how it handles them outside loops. The difference is that file.write
methods used to return None in Python 2, in Python 3 they return the
number of bytes written.
Oh! That would explain it, thanks for clarifying. So my justification
was wrong, though the solutions (assign the return value to something,
or run it in a script rather than the REPL) still apply.

ChrisA

Loading...