web-dev-qa-db-ja.com

pythonの新しい行ではなく、同じ行に出力します

基本的に私はこの男がやったことの反対をしたい... hehe。

Pythonスクリプト:既存の行を更新するのではなく、毎回新しい行をシェルに出力します

プログラムの進行状況を教えてくれるプログラムがあります。

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete"

したがって、len(some_list)が50だった場合、その最後の行が50回印刷されることになります。 1行を印刷し、その行を更新し続けたい。これはおそらく、あなたが一日中読んでいる最も遅い質問であることを知っています。答えを得るためにGoogleに入力する必要がある4つの単語がわかりません。

更新!正しいと思われるmvdsの提案を試しました。新しいコード

print percent_complete,"           \r",

完了率は単なる文字列です(最初は抽象化していたので、文字通りにしようとしています)。その結果、プログラムが実行され、プログラムが終了するまで何も出力せず、1行のみに「100%完了」が出力されます。

キャリッジリターンがない場合(ただし、mvdsの提案の半分であるコンマを使用する場合)、最後まで何も出力しません。そして、印刷:

0 percent complete     2 percent complete     3 percent complete     4 percent complete    

等々。新しい問題は、プログラムが終了するまでカンマでは印刷されないことです。

キャリッジリターンを使用し、カンマを使用しない場合、どちらも使用しない場合とまったく同じように動作します。

61
chriscauley

キャリッジリターン、または\rと呼ばれます

つかいます

print i/len(some_list)*100," percent complete         \r",

カンマは、printが改行を追加するのを防ぎます。 (そしてスペースは前の出力から行を明確に保ちます)

また、少なくとも最終的な改行を取得するために、print ""で終了することを忘れないでください!

73
mvds

python 3.xでできること:

print('bla bla', end='')

(Python 2.6または2.7でfrom __future__ import print_functionスクリプト/モジュールの上部)

Pythonコンソールのプログレスバーの例:

import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    n=0
    while n<total:
        done = '#'*(n+1)
        todo = '-'*(total-n-1)
        s = '<{0}>'.format(done+todo)
        if not todo:
            s+='\n'        
        if n>0:
            s = '\r'+s
        print(s, end='')
        yield n
        n+=1

# example for use of status generator
for i in range_with_status(10):
    time.sleep(0.1)
27
Remi

私にとって、働いたのはレミとシリウスの答えのコンボでした:

from __future__ import print_function
import sys

print(str, end='\r')
sys.stdout.flush()
21
dlchambers

コンソールにはおそらく必要になるでしょう

sys.stdout.flush()

強制的に更新します。 ,印刷中にstdoutのフラッシュがブロックされ、どういうわけか更新されません

12
siriusd

Python 3.3+では、sys.stdout.flush()は必要ありません。print('foobar', end='', flush=True)は動作します。

5
LeopardShark

これは私のために機能し、可能かどうかを確認するために一度ハッキングしましたが、実際に私のプログラムで使用されたことはありません(GUIははるかに優れています):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
    print clear+f % (i*100//123),
    time.sleep(0.4)
raw_input('\nDone')
3
import time
import sys


def update_pct(w_str):
    w_str = str(w_str)
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(" " * len(w_str))
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(w_str)
    sys.stdout.flush()

for pct in range(0, 101):
    update_pct("{n}%".format(n=str(pct)))
    time.sleep(0.1)

\bは、カーソルの位置を1スペース分戻します
そのため、行の先頭まで戻ります
次に、現在の行をクリアするためにスペースを書き込みます-スペースを書き込むと、カーソルが1つ前/右に移動します
したがって、新しいデータを書き込む前に、カーソルを行の先頭に戻す必要があります

Python 2.7を使用してWindows cmdでテスト済み

2
Robert

このようにしてみてください:

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete",

(末尾にコンマがあります。)

1
chryss

Remi answer forPython 2.7+これを使用します。

from __future__ import print_function
import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    import sys
    n = 0
    while n < total:
        done = '#' * (n + 1)
        todo = '-' * (total - n - 1)
        s = '<{0}>'.format(done + todo)
        if not todo:
            s += '\n'
        if n > 0:
            s = '\r' + s
        print(s, end='\r')
        sys.stdout.flush()
        yield n
        n += 1


# example for use of status generator
for i in range_with_status(50):
    time.sleep(0.2)
0
Francisco Costa

_Python 3.6+_およびlistsではなくintの場合、およびコンソールウィンドウの幅全体を使用し、新しい行に交差しないようにするには、次を使用できます。 :

注:関数get_console_with()はLinuxベースのシステムでのみ動作するため、Windowsで動作するように書き換える必要があることに注意してください。

_import os
import time

def get_console_width():
    """Returns the width of console.

    NOTE: The below implementation works only on Linux-based operating systems.
    If you wish to use it on another OS, please make sure to modify it appropriately.
    """
    return int(os.popen('stty size', 'r').read().split()[1])


def range_with_progress(list_of_elements):
    """Iterate through list with a progress bar shown in console."""

    # Get the total number of elements of the given list.
    total = len(list_of_elements)
    # Get the width of currently used console. Subtract 2 from the value for the
    # Edge characters "[" and "]"
    max_width = get_console_width() - 2
    # Start iterating over the list.
    for index, element in enumerate(list_of_elements):
        # Compute how many characters should be printed as "done". It is simply
        # a percentage of work done multiplied by the width of the console. That
        # is: if we're on element 50 out of 100, that means we're 50% done, or
        # 0.5, and we should mark half of the entire console as "done".
        done = int(index / total * max_width)
        # Whatever is left, should be printed as "unfinished"
        remaining = max_width - done
        # Print to the console.
        print(f'[{done * "#"}{remaining * "."}]', end='\r')
        # yield the element to work with it
        yield element
    # Finally, print the full line. If you wish, you can also print whitespace
    # so that the progress bar disappears once you are done. In that case do not
    # forget to add the "end" parameter to print function.
    print(f'[{max_width * "#"}]')


if __== '__main__':
    list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    for e in range_with_progress(list_of_elements):
        time.sleep(0.2)

_
0
tamaroth