Reputation:
I have following code in t.py:-
import time
for i in range(1,100):
print(f"{i}% \r",end='')
time.sleep(0.05)
it count 1 to 99 in single line like this:-
So when I execute following code, I expect the same
import subprocess as sb
import sys
lol = sb.Popen('python t.py',stdout=sb.PIPE,shell=True,text=True)
while True:
l = lol.stdout.read(1)
if not l and lol.poll() is not None:
break
if(l == '\n'): # for checking
print(" it should've been \\r") # this should not happen
sys.stdout.write(l)
sys.stdout.flush()
print("done")
But this code prints 1% to 99% in all separate line. like this:-
1% it should've been \r
2% it should've been \r
3% it should've been \r
4% it should've been \r
..... i have skipped this part .....
99% it should've been \r
done
So i added a little if statement
if(l == '\n'):
print(" it should've been \\r")
the above if statement shows that somehow '\r' might be converted into '\n' which I don't want.
Upvotes: 1
Views: 474
Reputation: 12503
Well, it's in the documentation: (https://docs.python.org/3.8/library/subprocess.html#frequently-used-arguments):
"If encoding or errors are specified, or text (also known as universal_newlines) is true, the file objects stdin, stdout and stderr will be opened in text mode using the encoding and errors specified in the call or the defaults for io.TextIOWrapper."
"For stdout and stderr, all line endings in the output will be converted to '\n'. For more information see the documentation of the io.TextIOWrapper class when the newline argument to its constructor is None."
Remove the text=True flag to avoid this behavior. When you do that, note that the stuff you read from stdout is now bytearrays and not strings, and you'll have to deal with them accordingly.
The following implementation of t.py and the main script achieves what you want.
t.py:
import time
import sys
for i in range(1,100):
print(f'{i} \r', end='')
sys.stdout.flush()
time.sleep(0.2)
Main script:
import subprocess as sb
import sys
lol = sb.Popen('python3 t.py',stdout=sb.PIPE,shell=True)
while True:
l = lol.stdout.read(1)
if not l and lol.poll() is not None:
break
print(l.decode("utf-8"), end="")
print("done")
Upvotes: 2