同じ行に出力して以前の出力を上書きしますか?


94

FTPダウンローダーを作成しています。コードの一部は次のようなものです:

ftp.retrbinary("RETR " + file_name, process)

私はコールバックを処理するために関数プロセスを呼び出しています:

def process(data):
    print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    file.write(data)

そして出力は次のようなものです:

1784  KB / KB 1829 downloaded!
1788  KB / KB 1829 downloaded!
etc...   

この行を印刷し、次回は再印刷/更新して、一度だけ表示され、ダウンロードの進行状況が表示されるようにしたいのですが。

どうすればできますか?



回答:


185

Python 3.xのコードは次のとおりです。

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!', end='\r')

end=キーワードは、ここでの作業を行うものである-デフォルトでは、print()改行(で終わる\n)の文字が、これは別の文字列に置き換えることができます。この場合、行をキャリッジリターンで終了すると、カーソルは現在の行の先頭に戻ります。したがって、sysこのような単純な使用法のためにモジュールをインポートする必要はありません。print()実際にはコードを大幅に簡略化するために使用できるいくつかのキーワード引数があります。

Python 2.6以降で同じコードを使用するには、ファイルの先頭に次の行を追加します。

from __future__ import print_function

6
ファイルの先頭に次のインポートを追加することにより、python 2.6以降でも印刷機能を使用できることに注意してくださいfrom __future__ import print_function
janin

12
Pythonで<文の末尾に3.0コンマは「\ n」を防ぐことができます: print "foo",あなたはまだ変更を確認するために、その後のフラッシュに必要しかし:sys.stdout.flush()
トビアスDomhan

29
\r文字列の先頭にを含め、end=''これを機能させるために代わりに設定する必要があることがわかりました。私が終了するとき、私の端末はそれが好きではないと思います\r
Jezzamon

2
現在のすべてのPython 3リリースではflush=Trueprint()関数を追加して、バッファーが確実にフラッシュされるようにすることができます(標準行バッファー\nは、改行が書き込まれたときにのみフラッシュされます)。
Martijn Pieters

4
jupyterノートブック\rでは、最初にを使用するend=''と、最もスムーズに動作しました。文字列の場合も最後にflush=Truewith \rを使用すると動作しend='\r'ましたが、スムーズでなく、行とその改行が消去されました。
Dave X

40

1行を変更するだけの場合は、を使用します\r\rキャリッジリターンを意味します。その効果は、キャレットを現在の行の先頭に戻すことだけです。何も消去しません。同様に、\b1文字後退するために使用できます。(一部の端末はこれらの機能をすべてサポートしていない場合があります)

import sys

def process(data):
    size_str = os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    sys.stdout.write('%s\r' % size_str)
    sys.stdout.flush()
    file.write(data)

1
\rキャリッジリターンを意味します。その効果は、キャレットを現在の行の先頭に戻すことだけです。何も消去しません。同様に、\b1文字後退するために使用できます。(一部の端末ではこれらすべての機能がサポートされていない場合があります)
Adrien Plisson

sys.stdout.write('%s\r', size_str')私はあなたが意味しsys.stdout.write('%s\r' % size_str)たと思うが、それは機能しません。
クリスチャン

@エイドリアン:クール、それを付け加えた。@クリスチャン:ありがとう、更新しました、かなり遅れました。
サム・ドーラン

また、あなたはまだ使用できますprintの代わりに、sys.stdout.writeご希望の場合:print size_str + "\r",罰金に動作します。,print文の末尾には改行を抑制し、sys.stdout.flush()まだ必要です
ジェフ

19

見てい呪いモジュールのマニュアル呪いモジュールHOWTOを

本当に基本的な例:

import time
import curses

stdscr = curses.initscr()

stdscr.addstr(0, 0, "Hello")
stdscr.refresh()

time.sleep(1)

stdscr.addstr(0, 0, "World! (with curses)")
stdscr.refresh()

10
残念ながら、cursesはUnixでのみ使用できます。OPは、自分のアプリケーションがターゲットにしているオペレーティングシステムを教えてくれませんでした...
Adrien Plisson

私はLinuxでの作業に慣れているので、モジュールのドキュメントでモジュールがUNIX専用であるという警告にさえ気づきませんでした。指摘してくれてありがとう、@ Adrien。
Andrea Spadaccini、2011

3
@AdrienPlisson、私はこの質問が何年も前に行われたことを知っていますが、実際にWindowsにCursesを取得できます:lfd.uci.edu/~gohlke/pythonlibs/#curses
Cold Diamondz '18

これをPythonインタープリターに貼り付けたところ、端末が機能しなくなりました。インタープリターを終了しても役に立たなかった。WTF ?!
allyourcode

2行目が1行目より短い場合に使用clrtoeolます。
Serge Stroobandt 2017

9

これがテキストのブロックを再印刷できる私の小さなクラスです。それは以前のテキストを適切にクリアするので、混乱を作成せずに古いテキストを短い新しいテキストで上書きできます。

import re, sys

class Reprinter:
    def __init__(self):
        self.text = ''

    def moveup(self, lines):
        for _ in range(lines):
            sys.stdout.write("\x1b[A")

    def reprint(self, text):
        # Clear previous text by overwritig non-spaces with spaces
        self.moveup(self.text.count("\n"))
        sys.stdout.write(re.sub(r"[^\s]", " ", self.text))

        # Print new text
        lines = min(self.text.count("\n"), text.count("\n"))
        self.moveup(lines)
        sys.stdout.write(text)
        self.text = text

reprinter = Reprinter()

reprinter.reprint("Foobar\nBazbar")
reprinter.reprint("Foo\nbar")

2
Windows 10まではこれらの制御文字をサポートする最初のウィンドウであるため、これはWindows 10まで機能しませんen.wikipedia.org/wiki/ANSI_escape_code
user136036

8

Python 2.7の単純な印刷ステートメントの場合は、の最後にカンマを付けるだけであることがわかりました'\r'

print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!\r',

これは他の非Python 3ソリューションよりも短いですが、維持するのもより困難です。


1
Python 2.7.10。何も出力されません。多分、あなたはそれをオンラインでコンパイルして、それがどのように機能しているかを確認するためのリンクを私たちに送ることができます...?
牧島

5

文字列の最後に '\ r'を追加し、print関数の最後にコンマを追加するだけです。例えば:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),

1
これはpython 3用ですか?もしそうなら、デフォルトのendパラメータが\nso u printに設定されているもの(...)KB downloaded!\r\n。私が間違っている?
SR

end = '\r'代わりにを使用すると、Python 3の問題が修正されます
Abhimanyu Pallavi Sudhir

4

私はスパイダー3.3.1-Windows 7-Python 3.6を使用していますが、フラッシュは必要ない場合があります。この投稿に基づく-https://github.com/spyder-ide/spyder/issues/3437

   #works in spyder ipython console - \r at start of string , end=""
import time
import sys
    for i in range(20):
        time.sleep(0.5)
        print(f"\rnumber{i}",end="")
        sys.stdout.flush()

1

pythonで前の行を上書きするために必要なことは、print関数にend = '\ r'を追加することです。この例をテストします。

import time
for j in range(1,5):
   print('waiting : '+j, end='\r')
   time.sleep(1)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.