动态打印一行

问题:动态打印一行

我想做几条给出标准输出的语句,但不要在语句之间看到换行符。

具体来说,假设我有:

for item in range(1,100):
    print item

结果是:

1
2
3
4
.
.
.

如何使它看起来像:

1 2 3 4 5 ...

更妙的是,是否可以打印单号最后一个号码,所以只有一个号码在屏幕上在同一时间?

I would like to make several statements that give standard output without seeing newlines in between statements.

Specifically, suppose I have:

for item in range(1,100):
    print item

The result is:

1
2
3
4
.
.
.

How get this to instead look like:

1 2 3 4 5 ...

Even better, is it possible to print the single number over the last number, so only one number is on the screen at a time?


回答 0

更改print item为:

  • print item, 在Python 2.7中
  • print(item, end=" ") 在Python 3中

如果要动态打印数据,请使用以下语法:

  • print(item, sep=' ', end='', flush=True) 在Python 3中

Change print item to:

  • print item, in Python 2.7
  • print(item, end=" ") in Python 3

If you want to print the data dynamically use following syntax:

  • print(item, sep=' ', end='', flush=True) in Python 3

回答 1

顺便说一句……如何每次都刷新它以便它在一个地方打印mi只需更改数字。

通常,这样做的方法是使用终端控制代码。这是一个非常简单的情况,对于该情况,您只需要一个特殊字符:用'\r'Python(和许多其他语言)编写的U + 000D CARRIAGE RETURN 。这是一个基于您的代码的完整示例:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

关于此的一些事情可能令人惊讶:

  • \r去的字符串,这样的开始,程序运行时,光标会一直在数字后。这不只是装饰性的:如果您反过来做的话,某些终端仿真器会非常混乱。
  • 如果您不包括最后一行,则在程序终止后,您的外壳程序将在数字的顶部显示其提示。
  • stdout.flush在某些系统上,这是必需的,否则您将不会获得任何输出。其他系统可能不需要它,但是它没有任何危害。

如果您发现这不起作用,那么您首先应该怀疑的是您的终端仿真器有问题。该vttest程序可以帮助你测试。

你可以更换stdout.write一个print声明,但我宁愿不要混淆print与直接使用的文件对象。

By the way…… How to refresh it every time so it print mi in one place just change the number.

In general, the way to do that is with terminal control codes. This is a particularly simple case, for which you only need one special character: U+000D CARRIAGE RETURN, which is written '\r' in Python (and many other languages). Here’s a complete example based on your code:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

Some things about this that may be surprising:

  • The \r goes at the beginning of the string so that, while the program is running, the cursor will always be after the number. This isn’t just cosmetic: some terminal emulators get very confused if you do it the other way around.
  • If you don’t include the last line, then after the program terminates, your shell will print its prompt on top of the number.
  • The stdout.flush is necessary on some systems, or you won’t get any output. Other systems may not require it, but it doesn’t do any harm.

If you find that this doesn’t work, the first thing you should suspect is that your terminal emulator is buggy. The vttest program can help you test it.

You could replace the stdout.write with a print statement but I prefer not to mix print with direct use of file objects.


回答 2

使用print item,使打印语句忽略换行符。

在Python 3中为print(item, end=" ")

如果希望每个数字都显示在同一位置,请使用示例(Python 2.7):

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

在Python 3中,它有点复杂。在这里,您需要刷新,sys.stdout否则在循环完成之前它不会打印任何内容:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()

Use print item, to make the print statement omit the newline.

In Python 3, it’s print(item, end=" ").

If you want every number to display in the same place, use for example (Python 2.7):

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

In Python 3, it’s a bit more complicated; here you need to flush sys.stdout or it won’t print anything until after the loop has finished:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()

回答 3

与其他示例一样,
我使用类似的方法,而不是花时间计算出最后的输出长度,等等,

我只是使用ANSI代码转义符移回到行的开头,然后在打印我的当前状态输出之前清除整行。

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

要在迭代循环中使用,您只需调用以下内容:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

在这里查看更多

Like the other examples,
I use a similar approach but instead of spending time calculating out the last output length, etc,

I simply use ANSI code escapes to move back to the beginning of the line and then clear that entire line before printing my current status output.

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

To use in your iteration loop you would just call something like:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

See more here


回答 4

您可以在打印语句中添加尾随逗号,以在每次迭代中打印空格而不是换行符:

print item,

另外,如果您使用的是Python 2.6或更高版本,则可以使用新的打印功能,该功能可以让您指定在要打印的每个项目的末尾甚至都不应该有空格(或者允许您指定要结束的任何位置)想):

from __future__ import print_function
...
print(item, end="")

最后,您可以通过从sys模块导入标准输出直接写入标准输出,该模块返回一个类似文件的对象:

from sys import stdout
...
stdout.write( str(item) )

You can add a trailing comma to your print statement to print a space instead of a newline in each iteration:

print item,

Alternatively, if you’re using Python 2.6 or later, you can use the new print function, which would allow you to specify that not even a space should come at the end of each item being printed (or allow you to specify whatever end you want):

from __future__ import print_function
...
print(item, end="")

Finally, you can write directly to standard output by importing it from the sys module, which returns a file-like object:

from sys import stdout
...
stdout.write( str(item) )

回答 5

更改

print item

print "\033[K", item, "\r",
sys.stdout.flush()
  • “ \ 033 [K”清除到行尾
  • \ r,返回到行的开头
  • flush语句确保它立即显示,以便您获得实时输出。

change

print item

to

print "\033[K", item, "\r",
sys.stdout.flush()
  • “\033[K” clears to the end of the line
  • the \r, returns to the beginning of the line
  • the flush statement makes sure it shows up immediately so you get real-time output.

回答 6

我认为一个简单的连接应该起作用:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)

I think a simple join should work:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)

回答 7

我在2.7上使用的另一个答案是仅打印“。”。每次循环运行(向用户表明事情还在运行)是这样的:

print "\b.",

打印“。” 每个字符之间没有空格。看起来更好一点,并且效果很好。\ b是那些想知道的退格字符。

Another answer that I’m using on 2.7 where I’m just printing out a “.” every time a loop runs (to indicate to the user that things are still running) is this:

print "\b.",

It prints the “.” characters without spaces between each. It looks a little better and works pretty well. The \b is a backspace character for those wondering.


回答 8

这么多复杂的答案。如果您拥有python 3,只需将其放在\r打印开始处,然后添加end='', flush=True到其中:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

这将原位写入0 foo bar,然后1 foo bar依此类推。

So many complicated answers. If you have python 3, simply put \r at the start of the print, and add end='', flush=True to it:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

This will write 0 foo bar, then 1 foo bar etc, in-place.


回答 9

要使数字彼此覆盖,可以执行以下操作:

for i in range(1,100):
    print "\r",i,

只要在第一列中打印该数字,它就应该起作用。

编辑:这是一个即使没有在第一栏中打印也可以使用的版本。

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

我应该注意,此代码已经过测试,并且可以在Windows的Windows 2.5的WIndows控制台中正常运行。根据另一些说法,可能需要刷新stdout才能看到结果。YMMV。

To make the numbers overwrite each other, you can do something like this:

for i in range(1,100):
    print "\r",i,

That should work as long as the number is printed in the first column.

EDIT: Here’s a version that will work even if it isn’t printed in the first column.

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

I should note that this code was tested and works just fine in Python 2.5 on Windows, in the WIndows console. According to some others, flushing of stdout may be required to see the results. YMMV.


回答 10

“顺便说一下……如何每次都刷新它,以便它在一个地方打印mi只需更改数字即可。”

这确实是一个棘手的话题。什么扎克建议(输出控制台控制代码)是实现这一目标的方法之一。

您可以使用(n)个curses,但这主要适用于* nixes。

在Windows上(这是有趣的部分),它很少被提及(我不明白为什么),您可以将Python绑定到WinAPI(默认情况下还与ActivePython一起使用http://sourceforge.net/projects/pywin32/)-它不是努力工作,效果很好。这是一个小例子:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

或者,如果要使用print(语句或函数,没有区别):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

win32console 模块使您可以使用Windows控制台执行更多有趣的事情…我不是WinAPI的忠实拥护者,但是最近我意识到,至少有一半的反对意见是由用C编写WinAPI代码引起的-pythonic绑定是更容易使用。

当然,所有其他答案都是不错的,而且是Python语言的,但是…如果我想在一行中打印怎么办?还是写多行文本,而不是清除并重新写相同的行?我的解决方案使这成为可能。

“By the way…… How to refresh it every time so it print mi in one place just change the number.”

It’s really tricky topic. What zack suggested ( outputting console control codes ) is one way to achieve that.

You can use (n)curses, but that works mainly on *nixes.

On Windows (and here goes interesting part) which is rarely mentioned (I can’t understand why) you can use Python bindings to WinAPI (http://sourceforge.net/projects/pywin32/ also with ActivePython by default) – it’s not that hard and works well. Here’s a small example:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

Or, if you want to use print (statement or function, no difference):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

win32console module enables you to do many more interesting things with windows console… I’m not a big fan of WinAPI, but recently I realized that at least half of my antipathy towards it was caused by writing WinAPI code in C – pythonic bindings are much easier to use.

All other answers are great and pythonic, of course, but… What if I wanted to print on previous line? Or write multiline text, than clear it and write the same lines again? My solution makes that possible.


回答 11

对于Python 2.7

for x in range(0, 3):
    print x,

对于Python 3

for x in range(0, 3):
    print(x, end=" ")

for Python 2.7

for x in range(0, 3):
    print x,

for Python 3

for x in range(0, 3):
    print(x, end=" ")

回答 12

In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep:  string inserted between values, default a space.
end:  string appended after the last value, default a newline.
In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep:  string inserted between values, default a space.
end:  string appended after the last value, default a newline.

回答 13

如果只想打印数字,则可以避免循环。

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100花费21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100花费491.466823551ms

If you just want to print the numbers, you can avoid the loop.

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 took 21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 took 491.466823551ms


回答 14

最好的方法是使用 \r角色

只需尝试以下代码:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays

The best way to accomplish this is to use the \r character

Just try the below code:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays

回答 15

在Python 3中,您可以这样操作:

for item in range(1,10):
    print(item, end =" ")

输出:

1 2 3 4 5 6 7 8 9 

元组:您可以对元组执行相同的操作:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

输出:

1 - 2 - 3 - 4 - 5 - 

另一个例子:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

输出:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

您甚至可以像这样打开元组的包装:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

输出:

1 2
A B
3 4
Cat Dog

另一个变化:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

输出:

1
2


A
B


3
4


Cat
Dog

In Python 3 you can do it this way:

for item in range(1,10):
    print(item, end =" ")

Outputs:

1 2 3 4 5 6 7 8 9 

Tuple: You can do the same thing with a tuple:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

Outputs:

1 - 2 - 3 - 4 - 5 - 

Another example:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

Outputs:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

You can even unpack your tuple like this:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

Outputs:

1 2
A B
3 4
Cat Dog

another variation:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

Outputs:

1
2


A
B


3
4


Cat
Dog

回答 16

打印语句末尾的逗号会省略新行。

for i in xrange(1,100):
  print i,

但这不会覆盖。

A comma at the end of the print statement omits the new line.

for i in xrange(1,100):
  print i,

but this does not overwrite.


回答 17

对于那些像我一样挣扎的人,我想出了以下似乎在python 3.7.4和3.5.2中都适用的代码。

我将范围从100扩展到1,000,000,因为它运行非常快,您可能看不到输出。这是因为设置的一个副作用end='\r'是最终循环迭代会清除所有输出。需要更长的数量才能证明其有效。此结果可能并非在所有情况下都令人满意,但在我的情况下还不错,并且OP没有指定一种方法或另一种方法。您可以使用if语句来评估要迭代的数组的长度,从而避免这种情况。在我的案例中,使其工作的关键是将方括号"{}".format()。否则,它不会起作用。

以下应按原样工作:

#!/usr/bin/env python3

for item in range(1,1000000):
    print("{}".format(item), end='\r', flush=True)

For those struggling as I did, I came up with the following that appears to work in both python 3.7.4 and 3.5.2.

I expanded the range from 100 to 1,000,000 because it runs very fast and you may not see the output. This is because one side effect of setting end='\r' is that the final loop iteration clears all of the output. A longer number was needed to demonstrate that it works. This result may not be desirable in all cases, but was fine in mine, and OP didn’t specify one way or another. You could potentially circumvent this with an if statement that evaluates the length of the array being iterated over, etc. The key to get it working in my case was to couple the brackets "{}" with .format(). Otherwise, it didn’t work.

Below should work as-is:

#!/usr/bin/env python3

for item in range(1,1000000):
    print("{}".format(item), end='\r', flush=True)

回答 18

for item in range(1,100):
    if item==99:
        print(item,end='')
    else:
        print (item,end=',')

输出:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49, 50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74, 75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99

for item in range(1,100):
    if item==99:
        print(item,end='')
    else:
        print (item,end=',')

Output: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99


回答 19

或更简单:

import time
a = 0
while True:
    print (a, end="\r")
    a += 1
    time.sleep(0.1)

end="\r" 从第一张打印的开始[0:]开始覆盖。

Or even simpler:

import time
a = 0
while True:
    print (a, end="\r")
    a += 1
    time.sleep(0.1)

end="\r" will overwrite from the beginning [0:] of the first print.