Печать в одной строке динамично

Я хотел бы сделать несколько операторов, которые дают стандартный вывод, не видя новых строк промежуточные операторы.

А именно, предположите, что я имею:

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

Результат:

1
2
3
4
.
.
.

Как заставляют это вместо этого быть похожим:

1 2 3 4 5 ...

Еще лучше действительно ли возможно распечатать единственное число по последнему числу, таким образом, только одно число находится на экране за один раз?

281
задан unutbu 6 August 2014 в 07:14
поделиться

9 ответов

Изменить элемент печати кому:

  • элемент печати, в Python 2.7
  • print (item, end = "") в Python 3

Если вы хотите распечатать данные динамически, используйте следующий синтаксис:

  • print (item, sep = '', end = '', flush = True) в Python 3
452
ответ дан 23 November 2019 в 01:59
поделиться

"Кстати...... Как обновлять его каждый раз, чтобы он печатал mi в одном месте, просто меняя номер."

Это действительно сложная тема. То, что предложил zack (вывод управляющих кодов консоли) - один из способов добиться этого.

Вы можете использовать (n)curses, но это работает в основном на *nix.

На Windows (и здесь начинается интересная часть), которая редко упоминается (я не могу понять почему) вы можете использовать привязку Python к WinAPI (http://sourceforge.net/projects/pywin32/ также с ActivePython по умолчанию) - это не так сложно и работает хорошо. Вот небольшой пример:

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, но недавно я понял, что по крайней мере половина моей антипатии к нему была вызвана написанием кода WinAPI на C - питонические привязки гораздо проще в использовании.

Все остальные ответы, конечно, замечательны и питоничны, но... Что если я хочу печатать на предыдущей строке? Или написать многострочный текст, затем очистить его и написать те же строки снова? Мое решение делает это возможным.

3
ответ дан 23 November 2019 в 01:59
поделиться

Чтобы числа перезаписывали друг друга, вы можете сделать что-то вроде этого:

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

Это должно работать, пока число выводится в первой колонке.

EDIT: Вот версия, которая будет работать, даже если номер не напечатан в первой колонке.

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

Я должен отметить, что этот код был протестирован и прекрасно работает в Python 2.5 на Windows, в консоли WIndows. По словам некоторых других, для просмотра результатов может потребоваться очистка stdout. YMMV.

3
ответ дан 23 November 2019 в 01:59
поделиться

Запятая в конце оператора печати пропускает новую строку.

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

, но при этом не перезаписывается.

0
ответ дан 23 November 2019 в 01:59
поделиться

Если вы хотите просто вывести числа, можно обойтись без цикла.

# 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.466823551мс

0
ответ дан 23 November 2019 в 01:59
поделиться
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.
1
ответ дан 23 November 2019 в 01:59
поделиться

Кстати...... Как обновлять его каждый раз, чтобы он печатал ми в одном месте, просто измените номер.

В общем, способ сделать это - коды управления терминалом. Это особенно простой случай, для которого нужен только один специальный символ: U+000D CARRIAGE RETURN, который в Python (и многих других языках) записывается '\r'. Вот полный пример, основанный на вашем коде:

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 с прямым использованием файловых объектов.

147
ответ дан 23 November 2019 в 01:59
поделиться

Используйте элемент печати, , чтобы оператор печати опускал новую строку.

В 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()
49
ответ дан 23 November 2019 в 01:59
поделиться

Вы можете добавить запятую в конце оператора print, чтобы печатать пробел вместо новой строки в каждой итерации:

print item,

Или же, если вы используете Python 2. 6 или более поздней версии, вы можете использовать новую функцию print, которая позволит вам указать, что в конце каждого выводимого элемента не должно быть пробела (или вы можете указать любой конец, какой захотите):

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

Наконец, вы можете писать непосредственно на стандартный вывод, импортировав его из модуля sys, который возвращает файлоподобный объект:

from sys import stdout
...
stdout.write( str(item) )
14
ответ дан 23 November 2019 в 01:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: