打印到同一行,而不是一个新的行?

基本上我想做的和这个家伙做的相反... 呵呵。

Python 脚本: 每次在 shell 中打印新行,而不是更新现有行

我有个程序可以告诉我进展如何。

for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete"

因此,如果 len (some _ list)为50,那么最后一行将被打印50次。我想打印一行,并不断更新该行。我知道这可能是你今天会读到的最烂的问题。我就是想不出要输入谷歌才能得到答案的四个词。

更新! 我尝试了 mvds 的建议,其中 SEEMED 的权利。新的代码

print percent_complete,"           \r",

完成百分比只是一个字符串(我第一次是抽象的,现在我试图是字面的)。现在的结果是,它运行程序,直到程序结束后才打印任何东西,然后只在一行上打印“100% 完成”。

如果没有回车符(但使用了逗号,只有 mvds 建议的一半) ,那么它直到结束才会打印出任何内容。然后打印:

0 percent complete     2 percent complete     3 percent complete     4 percent complete

诸如此类。所以现在的新问题是,使用逗号直到程序完成才会打印。

如果回车符没有逗号,那么它的行为与两者都没有完全相同。

156767 次浏览

It's called the carriage return, or \r

Use

print i/len(some_list)*100," percent complete         \r",

The comma prevents print from adding a newline. (and the spaces will keep the line clear from prior output)

Also, don't forget to terminate with a print "" to get at least a finalizing newline!

Try it like this:

for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete",

(With a comma at the end.)

This works for me, hacked it once to see if it is possible, but never actually used in my program (GUI is so much nicer):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
print clear+f % (i*100//123),
time.sleep(0.4)
raw_input('\nDone')

From python 3.x you can do:

print('bla bla', end='')

(which can also be used in Python 2.6 or 2.7 by putting from __future__ import print_function at the top of your script/module)

Python console progressbar example:

import time


# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
n=0
while n<total:
done = '#'*(n+1)
todo = '-'*(total-n-1)
s = '<{0}>'.format(done+todo)
if not todo:
s+='\n'
if n>0:
s = '\r'+s
print(s, end='')
yield n
n+=1


# example for use of status generator
for i in range_with_status(10):
time.sleep(0.1)

for Console you'll probably need

sys.stdout.flush()

to force update. I think using , in print will block stdout from flushing and somehow it won't update

For me, what worked was a combo of Remi's and siriusd's answers:

from __future__ import print_function
import sys


print(str, end='\r')
sys.stdout.flush()
import time
import sys




def update_pct(w_str):
w_str = str(w_str)
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(" " * len(w_str))
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(w_str)
sys.stdout.flush()


for pct in range(0, 101):
update_pct("{n}%".format(n=str(pct)))
time.sleep(0.1)

\b will move the location of the cursor back one space
So we move it back all the way to the beginning of the line
We then write spaces to clear the current line - as we write spaces the cursor moves forward/right by one
So then we have to move the cursor back at the beginning of the line before we write our new data

Tested on Windows cmd using Python 2.7

Based on Remi answer for Python 2.7+ use this:

from __future__ import print_function
import time


# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
import sys
n = 0
while n < total:
done = '#' * (n + 1)
todo = '-' * (total - n - 1)
s = '<{0}>'.format(done + todo)
if not todo:
s += '\n'
if n > 0:
s = '\r' + s
print(s, end='\r')
sys.stdout.flush()
yield n
n += 1




# example for use of status generator
for i in range_with_status(50):
time.sleep(0.2)

In Python 3.3+ you don’t need sys.stdout.flush(). print(string, end='', flush=True) works.

So

print('foo', end='')
print('\rbar', end='', flush=True)

will overwrite ‘foo’ with ‘bar’.

For Python 3.6+ and for any list rather than just ints, as well as using the entire width of your console window and not crossing over to a new line, you could use the following:

note: please be informed, that the function get_console_with() will work only on Linux based systems, and as such you have to rewrite it to work on Windows.

import os
import time


def get_console_width():
"""Returns the width of console.


NOTE: The below implementation works only on Linux-based operating systems.
If you wish to use it on another OS, please make sure to modify it appropriately.
"""
return int(os.popen('stty size', 'r').read().split()[1])




def range_with_progress(list_of_elements):
"""Iterate through list with a progress bar shown in console."""


# Get the total number of elements of the given list.
total = len(list_of_elements)
# Get the width of currently used console. Subtract 2 from the value for the
# edge characters "[" and "]"
max_width = get_console_width() - 2
# Start iterating over the list.
for index, element in enumerate(list_of_elements):
# Compute how many characters should be printed as "done". It is simply
# a percentage of work done multiplied by the width of the console. That
# is: if we're on element 50 out of 100, that means we're 50% done, or
# 0.5, and we should mark half of the entire console as "done".
done = int(index / total * max_width)
# Whatever is left, should be printed as "unfinished"
remaining = max_width - done
# Print to the console.
print(f'[{done * "#"}{remaining * "."}]', end='\r')
# yield the element to work with it
yield element
# Finally, print the full line. If you wish, you can also print whitespace
# so that the progress bar disappears once you are done. In that case do not
# forget to add the "end" parameter to print function.
print(f'[{max_width * "#"}]')




if __name__ == '__main__':
list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
for e in range_with_progress(list_of_elements):
time.sleep(0.2)


Late to the game - but since the none of the answers worked for me (I didn't try them all) and I've come upon this answer more than once in my search ... In python 3, this solution is pretty elegant and I believe does exactly what the author is looking for, it updates a single statement on the same line. Note, you may have to do something special if the line shrinks instead of grows (like perhaps make the string a fixed length with padded spaces at the end)

if __name__ == '__main__':
for i in range(100):
print("", end=f"\rPercentComplete: {i} %")
time.sleep(0.2)

If you are using Python 3 then this is for you and it really works.

print(value , sep='',end ='', file = sys.stdout , flush = False)

If you are using Spyder, the lines just print continuously with all the previous solutions. A way to avoid that is using:

for i in range(1000):
print('\r' + str(round(i/len(df)*100,1)) + '% complete', end='')
sys.stdout.flush()

For Python 3+

for i in range(5):
print(str(i) + '\r', sep='', end ='', file = sys.stdout , flush = False)

Just figured this out on my own for showing a countdown but it would also work for a percentage.

import time
#Number of seconds to wait
i=15
#Until seconds has reached zero
while i > -1:
#Ensure string overwrites the previous line by adding spaces at end
print("\r{} seconds left.   ".format(i),end='')
time.sleep(1)
i-=1
print("") #Adds newline after it's done

As long as whatever comes after '/r' is the same length or longer (including spaces) than the previous string, it will overwrite it on the same line. Just make sure you include the end='' otherwise it will print to a newline. Hope that helps!

for object "pega" that provides StartRunning(), StopRunning(), boolean getIsRunning() and integer getProgress100() returning value in range of 0 to 100, this provides text progress bar while running...

now = time.time()
timeout = now + 30.0
last_progress = -1


pega.StartRunning()


while now < timeout and pega.getIsRunning():
time.sleep(0.5)
now = time.time()


progress = pega.getTubProgress100()
if progress != last_progress:
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", end='', flush=True)
last_progress = progress


pega.StopRunning()


progress = pega.getTubProgress100()
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", flush=True)

As of end of 2020 and Python 3.8.5 on linux console for me only this works:

print('some string', end='\r')

Credit goes to: This post

As of 2021, for Python 3.9.0 the following solution worked for me in Windows 10, Pycharm.

print('\r some string ', end='', flush=True)

In those cases, with python 3.x, I'm using the following code:

for ii in range(100):
print(f"\rPercent: {ii+1} %", end=" "*20)

The problem with some other answers is that if your printed string goes shorter at one step, the last characters from the previous string won't be overwrited.

So I use end=" "*20 in order to overwrite the previous line with whitespace. Just make sure that 20 is longer than the length of your longest string.