Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sys.stdout.write in python3 adds 11 at end of string

Tags:

python

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
like image 474
linuxfan Avatar asked Sep 15 '15 02:09

linuxfan


2 Answers

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
like image 105
Yu Hao Avatar answered Sep 18 '22 07:09

Yu Hao


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
like image 38
bballdave025 Avatar answered Sep 21 '22 07:09

bballdave025