200

I am new to python and am writing some scripts to automate downloading files from FTP servers, etc. I want to show the progress of the download, but I want it to stay in the same position, such as:

output:

Downloading File FooFile.txt [47%]

I'm trying to avoid something like this:

     Downloading File FooFile.txt [47%]
     Downloading File FooFile.txt [48%]
     Downloading File FooFile.txt [49%]

How should I go about doing this?


Duplicate: How can I print over the current line in a command line application?

Community
  • 1
  • 1
scottm
  • 27,829
  • 22
  • 107
  • 159
  • 1
    you might be interested in this easy-to-use module, it's a text progress bar. http://pypi.python.org/pypi/progressbar/2.2 – wim Aug 16 '11 at 03:06
  • 1
    Does this answer your question? [Print in one line dynamically](https://stackoverflow.com/questions/3249524/print-in-one-line-dynamically) – mkrieger1 Apr 30 '23 at 15:34

9 Answers9

292

You can also use the carriage return:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()
UdayaLakmal
  • 4,035
  • 4
  • 29
  • 40
codelogic
  • 71,764
  • 9
  • 59
  • 54
  • 17
    Very common and simple solution. Note: if your line is longer than the width of your terminal, this gets ugly. – ephemient Feb 05 '09 at 18:24
  • 6
    I also had to add a call to sys.stdout.flush() so the cursor didn't bounce around – scottm Feb 05 '09 at 19:40
  • 22
    Is it possible to do this with multiple lines? Lets say I have three different downloads, and I want to show the progress of each one on its own line. – EarlCrapstone Apr 02 '14 at 14:56
  • 11
    I like to put the `\r` at the beginning of the line, and add a `\x1b[K` to clear the previous text. – augurar Oct 27 '14 at 05:48
  • 2
    What if I have multiple lines? For example, multiple downloads happening at the same time. It doesn't seem to work when I just add newlines, it prints infinitely. I.e., `sys.stdout.write("Download progress: %d%% \n\r" % (progress) )` doesnt work – Ogen May 23 '16 at 02:55
  • 28
    It seems like the simplest solution for python 3 (as mentioned in answers below) is: `print("sample text", end='\r", flush=True)` – Cyrus Feb 22 '18 at 22:20
  • 1
    @Cyrus that worked seamlessly. Just fix the quotes with `\r` :) – codesnerd Feb 28 '21 at 01:20
63

Python 2

I like the following:

print 'Downloading File FooFile.txt [%d%%]\r'%i,

Demo:

import time

for i in range(100):
    time.sleep(0.1)
    print 'Downloading File FooFile.txt [%d%%]\r'%i,

Python 3

print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

Demo:

import time

for i in range(100):
    time.sleep(0.1)
    print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

PyCharm Debugger Console with Python 3

# On PyCharm Debugger console, \r needs to come before the text.
# Otherwise, the text may not appear at all, or appear inconsistently.
# tested on PyCharm 2019.3, Python 3.6

import time

print('Start.')
for i in range(100):
    time.sleep(0.02)
    print('\rDownloading File FooFile.txt [%d%%]'%i, end="")
print('\nDone.')
Yul Kang
  • 449
  • 4
  • 9
RSabet
  • 6,130
  • 3
  • 27
  • 26
  • 11
    use this for python 3+: print('Downloading File FooFile.txt [%d%%]\r'%i, end="") – hkoosha May 15 '14 at 18:47
  • 1
    On PyCharm Debugger console, \r needs to come before the text. Otherwise, the text may not appear at all, or appear inconsistently. I added the version that works for me as an edit, because I couldn't write multi-line code in this answer. I put it on my gist so people can view it while the edit is awaiting approval: https://gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df – Yul Kang Mar 18 '20 at 12:53
  • "\r" at the end of the string works for me in the debugger console on PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build #PC-201.7846.77, built on May 31, 2020). – battey Jun 11 '20 at 22:25
  • What about 2 lines print ? – Sion C Jul 08 '22 at 07:47
  • minor detail it's possible to move the `\r` to the `end` parameter, like: `print('Downloading File FooFile.txt [%d%%]'%i, end='\r')` – Rafael Beirigo Oct 15 '22 at 21:56
29

Use a terminal-handling library like the curses module:

The curses module provides an interface to the curses library, the de-facto standard for portable advanced terminal handling.

gimel
  • 83,368
  • 10
  • 76
  • 104
16

Print the backspace character \b several times, and then overwrite the old number with the new number.

Zach Scrivena
  • 29,073
  • 11
  • 63
  • 73
15

For Python 3xx:

import time
for i in range(10):
    time.sleep(0.2) 
    print ("\r Loading... {}".format(i)+str(i), end="")
Kiara Grouwstra
  • 5,723
  • 4
  • 21
  • 36
TheRutubeify
  • 646
  • 1
  • 7
  • 24
9
#kinda like the one above but better :P

from __future__ import print_function
from time import sleep

for i in range(101):
  str1="Downloading File FooFile.txt [{}%]".format(i)
  back="\b"*len(str1)
  print(str1, end="")
  sleep(0.1)
  print(back, end="")
4

A neat solution that has been working for me is:

from __future__ import print_function
import sys
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r')
    sys.stdout.flush()
print("")

The sys.stdout.flush is important otherwise it gets really clunky and the print("") on for loop exit is also important.

UPDATE: As mentioned in the comments, print also has a flush argument. So the following will also work:

from __future__ import print_function
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r', flush=True)
print("")
Michael Hall
  • 2,834
  • 1
  • 22
  • 40
  • 1
    In modern Python, you can supply an arg of `flush=True` to `print`, so there's no need for the extra `sys.stdout.flush()` call. – PM 2Ring Nov 09 '17 at 16:02
1

In python 3 the function print can get many arguments. the full signature of the function print is: print(args*, sep=' ', end='\n', file=sys.stdout, flush=False)

when sep is the separator of the arguments from args*, end is how to end the printed line ('\n\ means a new line) file is to where print the output (stdout is the consul) and flush is if to clean the buffer.

Usage Example

import sys

a = 'A'
b = 0
c = [1, 2, 3]

print(a, b, c, 4, sep=' * ', end='\n' + ('-' * 21), file=sys.stdout, flush=True)

Output

A * 0 * [1, 2, 3] * 4
---------------------

In python there are many ways to format string and even a built in formatted string type.

How to format string

  1. the format() function. (some examples)
  2. Formatted String Literals or in the common name f-strings.
  3. format using % (more about this)

Examples

name = 'my_name'

>>> print('my name is: {}'.format(name))
my name is: my_name

# or
>>> print('my name is: {user_name}'.format(user_name=name))
my name is: my_name

# or
>>> print('my name is: {0}'.format(name))
my name is: my_name

# or using f-strings
>>> print(f'my name is: {name}')
my name is: my_name

# or formatting with %
>>> print('my name is: %s' % name)
my name is: my_name
Ido
  • 168
  • 9
0
x="A Sting {}"
   for i in range(0,1000000):
y=list(x.format(i))
print(x.format(i),end="")

for j in range(0,len(y)):
    print("\b",end="")