8

Can someone explain why sys.stdout.write() appends 11 to my string?

$ python3
Python 3.4.3+ (default, Jul 28 2015, 13:17:50) 
[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> x = 'hello'
>>> y = 'world'
>>> msg = ''
>>> import sys
>>> msg += x
>>> msg += '\n' + y 
>>> msg
'hello\nworld'
>>> sys.stdout.write(msg)
hello
world11
>>> print(msg)
hello
world
2
  • interesting. try sys.stdout.write(msg+'\n'), will add 12 at next line. But when I save the code to a file and run it, it's no problem. Commented Sep 15, 2015 at 2:15
  • Reproduced on Python 3.4.3 on Windows. Commented Sep 15, 2015 at 2:17

2 Answers 2

15

It's NOT appended to the written string. 11 here is the return value of sys.stdout.write(), which is the number of characters written.

See write:

Write the string s to the stream and return the number of characters written.


It's similar to:

>>> def foo():
...     print('something', end='')
...     return 42
...
>>> foo()
something42
Sign up to request clarification or add additional context in comments.

2 Comments

Duh - that was lame. Thanks
This is only the behavior for the interactive console.
4

A More General Question

This is a great question, but I don't believe it to be the most general. The question, Python 3 interpreter prints length to standard input for every write, is easier to find if the string someone is trying to write happens to be a different length than 11. When I say "easier to find", I mean that it shows up more readily in a search. Also, the question I refer to includes a further question of "How do I fix this?"

The issue in both posts is an interpreter vs. script issue. Technically the Python shell (at least with the Python straight from python.org and default setup) uses a Read-eval-print loop (REPL), which you can read about in the previous link. More simply (and as stated by @Kieran in the answer to the other post I referred to)

[T]he python executable doesn't show returned values whereas the interpreter does.


How To Fix It

I think that's the shell vs. script issue has been well described in the question here. However, I want to address the question of "How to make it go away?" here. First of all, I think people that stumble on this question might wonder, especially if they use the interactive shell for development. Second of all, I can't answer this second, "How?" question with the other post being marked duplicate.

I'll repeat some of the code there with results, mostly because it's a bit quicker. As noted by @Yu_Hao , the documentation for write helps explain the behavior.

Write the string s to the stream and return the number of characters written.

The simple way to fix this is to assign the return value to a variable. (This is a good practice anyway, since it's good to know if a script called by another script completed successfully.) Here's a series of commands showing the problem, the reason, the solution, and a further use of the solution to make sure it worked.

(Windows) >python
(*NIX)    $ python3
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [<system-dependent-string>] on <system>
Type "help", "copyright", "credits" or "license" for more information.
>>> with open("garbage.file", "wb") as f:
...   for x in range(4):
...     f.write(b"xyz")
...
3
3
3
3
>>> with open("garbage.file", "wb") as f:
...   for x in range(4):
...     catch_ret_val = f.write(b"xyz")
...
>>> # Check it.
...
>>> with open("garbage.file", 'rb') as f:
...   f.read()
...
b'xyzxyzxyzxyz'
>>>
>>> # Note a snag if you want to use another way to check it.
...
>>> import os
(Windows) >>> os.system("type garbage.file")
xyzxyzxyzxyz0
(*NIX)    >>> os.system("cat garbage.file")
xyzxyzxyzxyz0
>>>
>>> # Oops, the return value of zero gets added on. 
...
>>> # We can use the same solution with the return value.
(Windows) >>> os_ret = os.system("type garbage.file")
xyzxyzxyzxyz>>>
(*NIX)    >>> os_ret = os.system("cat garbage.file")
xyzxyzxyzxyz>>>
>>>

Things still don't look quite nice. There's no carriage return and/or linefeed at the end of the file. If you want things a little cleaner...

(Windows) >>> os_ret = os.system("type garbage.file && echo(")
xyzxyzxyzxyz
(*NIX)    >>> os_ret = os.system("cat garbage.file && printf '\n'")
xyzxyzxyzxyz

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.