コンソールの同じ場所に出力を書き込むにはどうすればよいですか?


158

私はpythonが初めてで、FTPサーバーからのファイルのダウンロードなどを自動化するスクリプトを書いています。ダウンロードの進行状況を表示したいのですが、次のように同じ位置に留めておきます。

出力:

ファイルFooFile.txtのダウンロード[47%]

私はこのようなものを避けようとしています:

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

これを行うにはどうすればよいですか?


複製コマンドラインアプリケーションで現在の行に印刷するにはどうすればよいですか。


1
この使いやすいモジュールは、テキストプログレスバーです。 pypi.python.org/pypi/progressbar/2.2
wim

回答:


254

キャリッジリターンを使用することもできます。

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()

13
非常に一般的でシンプルなソリューション。注:線が端末の幅より長い場合、これは醜くなります。
ephemient

5
また、sys.stdout.flush()への呼び出しを追加して、カーソルがバウンドしないようにしなければなりませんでした
scottm

19
これを複数の行で行うことは可能ですか?3つの異なるダウンロードがあり、それぞれの進行状況を独自の行で表示したいとします。
EarlCrapstone 2014

11
\r行の先頭にを置き\x1b[K、前のテキストをクリアするためにa を追加するのが好きです。
オーギュラー2014年

11
:ある(下記の回答で述べたように)Pythonの3のための最も簡単な解決策のように思える print("sample text", end='\r", flush=True)
サイラス

35

Python 2

私は以下が好きです:

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

デモ:

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="")

デモ:

import time

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

Python 3を使用したPyCharmデバッガコンソール

# 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.')

9
これをpython 3以降で使用します。print( 'Downloading File FooFile.txt [%d %%] \ r'%i、end = "")
hkoosha

PyCharmデバッガーコンソールでは、\ rをテキストの前に置く必要があります。そうしないと、テキストがまったく表示されないか、一貫性のないように表示される場合があります。この回答で複数行のコードを記述できなかったため、私に役立つバージョンを編集として追加しました。編集が承認を待っている間、人々がそれを見ることができるように、それを私の要点に置きました:gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang

文字列の末尾の「\ r」は、PyCharm 2020.1(PyCharm 2020.1.2(Community Edition); Build#PC-201.7846.77、2020年5月31日ビルド)のデバッガーコンソールで機能します。
バッティ

28

cursesモジュールのような端末処理ライブラリを使用します

cursesモジュールは、ポータブルな高度な端末処理の事実上の標準であるcursesライブラリへのインターフェースを提供します。


1
Windowsでは使用できません。
ディエゴヘランツ2013

3
@Diego Windowsにcursesモジュールのサポートライブラリが追加されました。stackoverflow.com/a/19851287/1426237を
Plexico、2013年

15

バックスペース文字を\b数回印刷してから、古い番号を新しい番号で上書きします。


興味深いことに、私はそのようにするつもりはありませんでした。
Chris Ballance、

以前のコマンドがクリアされないため、これが好きです(画面に残したい複数のステージがある場合)
Nathan Donnellan

3
キャリッジリターン(などprint 'Downloading.... \r')を使用しても以前のデータは消去されませんが、どのくらい前にバックアップするかを知る必要がなくなります。
cod3monk3y 2014

8
#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="")

なぜこれが上記より優れているのですか(私はPython n00bなので、無知を許してください:-))?
BalinKingOfMoria CMを2016

7

Python 3xxの場合:

import time
for i in range(10):
    time.sleep(0.2) 
    print ("\r Loading... {}".format(i)+str(i), end="")

4

私のために働いているきちんとした解決策は:

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

これsys.stdout.flushは重要です。それ以外の場合は非常に扱いにくくなり、print("")on forループの終了も重要です。

更新:コメントで述べたように、議論printもありflushます。したがって、以下も機能します:

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

1
最新のPythonでは、flush=Truetoの引数を指定できるprintため、追加のsys.stdout.flush()呼び出しは必要ありません。
PM 2Ring 2017年

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