Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use \r to print on same line? [duplicate]

I have made a downloader:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from __future__ import print_function, division, absolute_import, unicode_literals
import os
import argparse
try:
    from urllib2 import urlopen
except ImportError:
    from urllib.request import urlopen

# {{ Argument parser
parser = argparse.ArgumentParser(
    prog='downloader',
    description='a featureful downloader'
)

parser.add_argument(
    '-o',
    dest='outputfile'
)

parser.add_argument(
    '-r',
    dest='remotefile'
)

downloader = parser.parse_args()
# }}

# {{ default local filename
if downloader.outputfile:
    default_output_file = downloader.outputfile
else:
    default_output_file = os.path.split(downloader.remotefile)[-1]
# }}

u = urlopen(downloader.remotefile)
meta = u.info()
file_size  = int(dict(meta.items())['Content-Length'])
print("Downloading: %s Bytes: %s" % (default_output_file, file_size))

with open(default_output_file, 'wb') as f:
    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print(status)

A sample run of this script would be:

python3 downloader.py -o ubuntu.iso -r http://releases.ubuntu.com/13.04/ubuntu-13.04-desktop-i386.iso

And a sample output will be:

Downloading: ubuntu.iso Bytes: 832569344
      8192  [0.00%]
     16384  [0.00%]
     24576  [0.00%]
     32768  [0.00%]
     40960  [0.00%]
     49152  [0.01%]
     57344  [0.01%]
     65536  [0.01%]
     73728  [0.01%]
     81920  [0.01%]
     90112  [0.01%]
     98304  [0.01%]
    106496  [0.01%]
    114688  [0.01%]
    122880  [0.01%]
    131072  [0.02%]
    139264  [0.02%]
    147456  [0.02%]
    155648  [0.02%]
    163840  [0.02%]

Note that as the loop goes the output is printed on a separate lines. I know I can use \r (carriage return) to do that. But I have confusion where and how to use that.

like image 979
Santosh Kumar Avatar asked Jun 30 '13 14:06

Santosh Kumar


People also ask

What does print \r do?

The '\r' character is the carriage return, and the carriage return-newline pair is both needed for newline in a network virtual terminal session.

How do I keep print on the same line?

Modify print() method to print on the same line The print method takes an extra parameter end=” “ to keep the pointer on the same line. The end parameter can take certain values such as a space or some sign in the double quotes to separate the elements printed in the same line.

What does \r do in Python?

In Python strings, the backslash "\" is a special character, also called the "escape" character. It is used in representing certain whitespace characters: "\t" is a tab, "\n" is a newline, and "\r" is a carriage return. Conversely, prefixing a special character with "\" turns it into an ordinary character.


3 Answers

Put the \r at the beginning or end of your printed string, e.g. '\rthis string will start at the beginning of the line'. or 'the next string will start at the beginning of the line\r'. Conceptually, \r moves the cursor to the beginning of the line and then keeps outputting characters as normal.

You also need to tell print not to automatically put a newline character at the end of the string. In python3, you can use end="" as in this previous stackoverflow answer.

Alternatively, instead of using print you can do import sys and sys.stdout.write('whatever'), which sends only the exact characters to stdout without an implicit newline. You'll probably also want to use sys.stdout.flush(), without which it will store characters in a buffer rather than printing them immediately.

like image 67
inclement Avatar answered Nov 10 '22 11:11

inclement


Add an , end="\r" to you print function. Also make sure your printed data has enough space to overwrite the previous printed data or be of the same length since just moving to the same line would not automatically clear the previous contents.

like image 20
Ayman Avatar answered Nov 10 '22 11:11

Ayman


You can use sys.stdout.write:

import time
import sys

def timer(t=5):
    t0 = time.time()
    now = t0
    while now-t0 < t:
        now = time.time()
        timestr = '\r%%%i\t' %(100*(now-t0)/t)
        sys.stdout.write(timestr)
        sys.stdout.flush()
        time.sleep(0.1)
like image 2
ali_m Avatar answered Nov 10 '22 11:11

ali_m