1行で動的に印刷する


306

ステートメント間の改行を表示せずに、標準出力を提供するいくつかのステートメントを作成したいと思います。

具体的には、私が持っていると仮定します:

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

結果は次のとおりです。

1
2
3
4
.
.
.

代わりにこれをどのように見せるか:

1 2 3 4 5 ...

さらに良いことに、最後の番号の上に単一の番号を印刷することが可能であり、一度に1つの番号のみが画面に表示されますか?


回答:


482

に変更print item

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

データを動的に印刷する場合は、次の構文を使用します。

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

http://docs.python.org/reference/simple_stmts.html#printから:> ステートメントがコンマで終わってい'\n'ない限り、文字は最後に書かれprintます。これは、ステートメントにキーワードのみが含まれている場合の唯一のアクションですprint
ewall 2013年

5
参考:print(item、end = "")は、ファイルの先頭に「from future import print_function」を追加することにより、Python2.7で使用できます。
2016

2
しかし、flushでは動作しませんfrom __future__ import print_function、残念ながら。
Timmmm 2018

私が何をした場合@ewall print(item, end=", ")それを、その後も追加,追加してからそれを防ぐ方法を行うために、最後の項目に,最後の項目に
MarcoBianchi

@SamirTendulkar元の質問のようにforループを使用している場合、リストの最後の項目を別の方法で処理する特別なケースを作成できます...
ewall

156

ちなみに……毎回リフレッシュして一箇所にmiを印刷する方法は数字を変えるだけ。

一般に、その方法は端末制御コードを使用することです。これは、'\r'Python(および他の多くの言語)で記述された1つの特殊文字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.writeprint声明が、私はミックスしたくないprintファイルオブジェクトを直接使用して。


flush()関数とは何ですか?その機能がなくても私にはうまくいくので!
Pol

1
通常、Pythonのファイルオブジェクトはデータを蓄積して、オペレーティングシステムに大きなチャンクで送信できるようにします。これは通常、ディスク上のファイルにアクセスするために必要なことですが、この種のタスクを妨害します。 flush()現在のファイルをオペレーティングシステムに送信します。それがなくても機能することに驚いています。追加するまで機能しませんでした。
zwol 2010

1
@ user1995839カーソルを非表示にする制御コードがありますが、そうする場合は、を使用ncursesしてカーソルを非表示にすることを強くお勧めします。
zwol 2014

1
sys.stdout.flush()私のmendatoryのようだFreebsdPython 2.7
ハキム

1
キャリッジリターンはPython REPL内では正しく機能しないことに注意してください(少なくとも私にとっては、Ubuntuの場合)。これを機能させるには、REPLコマンドを実行するだけでなく、スクリプトを実行する必要があります。
Mark Amery 2017年

50

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()

実際には、あなたのソリューションは毎回同じ数のバックスペースを出力するように見えます。したがって、toが20の場合、数字1..9を印刷するときに余分なバックスペースを印刷します。ループ内の数字を計算し、それをiの値に基づくべきではありませんか?
アダムクロスランド2010

それは数を右揃えし、常にすべてを削除します。それを行う方が速いか、または各反復で今すぐ消去する桁数​​を計算する方が速いかどうかはテストしていません。
Tim Pietzcker 2010

または、桁数が変化したときに考慮に入れるために、iの以前の値に基づいてそれを基にします。
アダムクロスランド2010

ああ、はい、私は正しい正当化を見落としていた。良い解決策。
アダムクロスランド2010

かなり複雑に聞こえます。1年後に自分のコードを見る必要があるとしたら、おそらく私がそこで何をしたのか理解できないでしょう。(私が2007年に書いたプログラムを読まなければならなかった
-Pythonで

16

他の例と同様に、
私は同様のアプローチを使用しますが、最後の出力長などを計算するために時間を費やすのではなく、

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   

詳細はこちら


14

各反復で改行の代わりにスペースを印刷するために、末尾のコンマを印刷ステートメントに追加できます。

print item,

または、Python 2.6以降を使用している場合は、新しい印刷関数を使用できます。これにより、印刷される各項目の末尾にスペースすらもないように指定できます(または、任意の末尾を指定できます)欲しいです):

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

最後に、ファイルのようなオブジェクトを返すsysモジュールからインポートすることにより、標準出力に直接書き込むことができます。

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

13

変化する

print item

print "\033[K", item, "\r",
sys.stdout.flush()
  • 「\ 033 [K」は行末までクリア
  • \ r、行の先頭に戻ります
  • flushステートメントは、それがすぐに表示されるようにし、リアルタイムの出力を取得します。

これはPython 2.7に最適です。\033[Kコードについて学んだ場所への参照を提供できますか?それらについてもっと知りたいのですが。
Klik

print既に内部的にフラッシュしています。呼び出す必要はありません。画面にフラッシュする必要がある場所とprintは異なりsys.stdout.write()ます
ガブリエルフェア

5

単純な結合でうまくいくと思います:

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

4
理解度は、より良く、おそらくより速くなります:print ' '.join(str(x) for x in range(1, 10))
ムーマインド

次に、リスト内包表記の使用について説明します。この場合、読みやすくなります。
オースティンヘンリー2012

5

「。」を出力する2.7で使用している別の答え。ループが実行されるたびに(物事がまだ実行中であることをユーザーに示すため)、次のようになります。

print "\b.",

「。」を出力します。それぞれの間にスペースのない文字。それは少し良く見え、かなりうまくいきます。\ bは不思議に思う人のためのバックスペース文字です。


4

非常に多くの複雑な答え。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、同様に書き込まれます。


ありがとう、それが私が必要としていたことでしたprint('\r' + filename + " ", end = '', flush=True)
McPeppr

3

数値を互いに上書きするには、次のようにします。

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上のPython 2.5で問題なく機能することに注意してください。他の人によると、結果を表示するにはstdoutのフラッシュが必要になる場合があります。YMMV。


3

「ちなみに……一箇所でmiを印刷するように毎回更新する方法は数を変えるだけ。」

それは本当にトリッキーなトピックです。何ザック(コンソール制御コードを出力)を示唆してそれを達成する一つの方法です。

(n)cursesを使用できますが、これは主に* nixesで機能します。

Windows(およびここで興味深い部分)ではめったに言及されませんが(理由は理解できません)、WinAPIへのPythonバインディングを使用できます(デフォルトでは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コードの記述が原因であることに気付きました-Pythonバインディングははるかに使いやすい。

もちろん、他のすべての答えは素晴らしく、pythonicですが、... 前の行に印刷したい場合はどうなりますか?または、複数行のテキストを書いて、それをクリアして同じ行をもう一度書くのですか?私のソリューションはそれを可能にします。



1
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.

0

数値を出力するだけの場合は、ループを回避できます。

# 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ミリ秒かかりました


の代わりにリスト内包を使用すると、さらに高速になるはずですmap
cji 10/07/14

はい良い例です。気に入ったのですが、解析結果を表示する必要があります。最初に、データベースのアイテムを数え、残りの量を印刷します。
Pol

0

これを達成する最良の方法は、\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

0

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

私はここですべての例を試してみましたが、Python 3.8では何も機能しません。もっと答えを入手してください。
KOTZ

私はそれをpython 3.7でテストしました
Stryker

つまり、質問の最後で提案されたように、これらのオプションは最後の番号を上書きしません。
KOTZ

0

printステートメントの最後のコンマは、新しい行を省略します。

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

しかし、これは上書きしません。


0

私のように苦労している人のために、私はpython 3.7.4と3.5.2の両方で動作するように見える次のことを思いつきました。

実行速度が非常に速く、出力が表示されない可能性があるため、100から1,000,000に範囲を拡大しました。これは、設定の副作用の1つend='\r'として、最後のループの反復によりすべての出力がクリアされるためです。それが機能することを示すには、より長い数が必要でした。この結果はすべての場合に望ましいわけではありませんが、私の場合は問題がなく、OPは何らかの方法を指定していませんでした。反復される配列の長さを評価するifステートメントなどでこれを回避できる可能性があります。私の場合、これを機能させるための鍵は、角かっこを"{}"と結合することでした.format()。それ以外の場合は、機能しませんでした。

以下はそのまま動作します:

#!/usr/bin/env python3

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

0
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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.