पायथन में कंसोल आउटपुट बदलें


106

मैं सोच रहा हूँ कि मैं उन निफ्टी कंसोल काउंटरों में से एक को कुछ C / C ++ प्रोग्रामों में कैसे बना सकता हूँ।

मुझे काम करने के लिए एक लूप मिला है और वर्तमान आउटपुट निम्न के साथ है:

Doing thing 0
Doing thing 1
Doing thing 2
...

क्या होगा, सिर्फ अंतिम पंक्ति का अद्यतन करने के लिए भोजनालय होगा;

X things done.

मैंने इसे कई सांत्वना कार्यक्रमों में देखा है और सोच रहा हूं कि क्या / कैसे मैं पायथन में ऐसा करूंगा।


3
आपको शाप पर एक नजर डालनी चाहिए ।
— ब्योर्न पोलेक्स

2
बस उपयोग करें print: stackoverflow.com/a/8436827/1959808
— Ioannis Filippidis

1
@ BjörnPollex, cursesएक ओवरकिल है (स्वीकृत उत्तर देखें)।
— एलेक्सी

जवाबों:


151

एक आसान समाधान "\r"स्ट्रिंग से पहले लिख रहा है और एक नई पंक्ति नहीं जोड़ रहा है; यदि स्ट्रिंग कभी छोटी नहीं होती है तो यह पर्याप्त है ...

sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()

थोड़ा और अधिक परिष्कृत एक प्रगति पट्टी है ... यह कुछ ऐसा है जिसका मैं उपयोग कर रहा हूं:

def startProgress(title):
    global progress_x
    sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write("#" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write("#" * (40 - progress_x) + "]\n")
    sys.stdout.flush()

आप startProgressऑपरेशन के विवरण को पास करना कहते हैं , फिर प्रतिशत और अंत में progress(x)कहां xहैendProgress()


2
क्या होगा यदि स्ट्रिंग पिछले एक से कम है?
— math2001

6
@ व्हाट्सएप के साथ math2001 पैडिंग।
— felipsmartins

कोड की केवल पहली 2 पंक्तियों के लिए वोट किया गया। कुछ मामलों में प्रगति बार भाग धीमा हो रहा है। वैसे भी धन्यवाद @ 6502
— वाटररकेट 8236

कुछ प्रोग्राम ( restic, flatpak) कंसोल आउटपुट की कई लाइनें अपडेट कर सकते हैं। क्या आप किसी भी मौके से जानते हैं कि यह कैसे हासिल किया जा सकता है?
— एलेक्सी

1
@Alexey: आप कर्सर को इधर-उधर करने के लिए ANSI एस्केप कोड का उपयोग कर सकते हैं, स्क्रीन के स्पष्ट भाग और रंग बदल सकते हैं ... en.wikipedia.org/wiki/ANSI_escape_code
— 6502

39

एक और अधिक सुंदर समाधान हो सकता है:

def progressBar(current, total, barLength = 20):
    percent = float(current) * 100 / total
    arrow   = '-' * int(percent/100 * barLength - 1) + '>'
    spaces  = ' ' * (barLength - len(arrow))

    print('Progress: [%s%s] %d %%' % (arrow, spaces, percent), end='\r')

इस फ़ंक्शन को कॉल करें valueऔर endvalue, परिणाम होना चाहिए

Progress: [------------->      ] 69 %

नोट: अजगर 2.x संस्करण यहाँ ।


आपको बेहतर प्रगति बार और स्पिनरों के लिए हेलो का उपयोग करना चाहिए ।
— अरविंद वोगगु

17

में अजगर 3 आप एक ही लाइन पर मुद्रित करने के लिए ऐसा कर सकते हैं:

print('', end='\r')

नवीनतम अद्यतन और प्रगति का ट्रैक रखने के लिए विशेष रूप से उपयोगी है।

अगर मैं एक लूप की प्रगति देखना चाहता हूं, तो मैं यहां से tqdm की भी सिफारिश करूंगा । यह परिष्करण के अपेक्षित समय के साथ एक प्रगति पट्टी के रूप में वर्तमान पुनरावृत्ति और कुल पुनरावृत्तियों को प्रिंट करता है। सुपर उपयोगी और त्वरित। Python2 और python3 के लिए काम करता है।


7

अन्य उत्तर बेहतर हो सकता है, लेकिन यहाँ मैं क्या कर रहा था। सबसे पहले, मैंने एक कार्य किया जिसे प्रगति कहा जाता है जो बैकस्पेस वर्ण को प्रिंट करता है:

def progress(x):
    out = '%s things done' % x  # The output
    bs = '\b' * 1000            # The backspace
    print bs,
    print out,

तब मैंने इसे अपने मुख्य कार्य में लूप में बुलाया जैसे:

def main():
    for x in range(20):
        progress(x)
    return

यह निश्चित रूप से पूरी रेखा को मिटा देगा, लेकिन आप इसके साथ गड़बड़ कर सकते हैं कि आप क्या चाहते हैं। मैंने इस पद्धति का उपयोग करते हुए एक प्रगति पट्टी बनाई।


4
काम करता है, लेकिन अगर पिछली पंक्ति में अगले की तुलना में अधिक वर्ण होते हैं, तो नई लाइन के अंत के बाद के अक्षर पिछली पंक्ति से बने रहते हैं: "वर्तनी जाँच रिकॉर्ड 417/701 [सतह पर बदल गया] जब uminescence [सं-पु।] स्मरणात्मकता] "
— लिल 'बिट्स

7

जो कोई भी इस साल बाद में ठोकर खाता है (जैसे मैंने किया था), मैंने 6502 के तरीकों को थोड़ा बढ़ाया और प्रगति पट्टी को कम करने के साथ-साथ वृद्धि की अनुमति दी। थोड़ा और मामलों में उपयोगी है। एक महान उपकरण के लिए धन्यवाद 6502!

मूल रूप से, अंतर केवल इतना है कि #s और -s की पूरी पंक्ति को हर बार प्रगति (x) लिखा जाता है और कर्सर हमेशा पट्टी की शुरुआत में वापस आ जाता है।

def startprogress(title):
    """Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character"""
    global progress_x
    sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    """Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50"""
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    """End of progress bar;
    Write full bar, then move to next line"""
    sys.stdout.write("#" * 40 + "]\n")
    sys.stdout.flush()

1
मैंने हालांकि पाया है कि यह कुछ मंदी का कारण बन सकता है अगर इसे कोड द्वारा बहुत बार कहा जाता है, तो मुझे लगता है YMMV
— jat255

6

अगर मैं अच्छी तरह से समझ गया (सुनिश्चित नहीं है) तो आप का उपयोग करके प्रिंट करना चाहते हैं <CR>और नहीं <LR>?

यदि ऐसा संभव है, तो जब तक कंसोल टर्मिनल इसे अनुमति देता है (यह तब टूटेगा जब आउटपुट सी एक फ़ाइल में रीडायरेक्ट हो जाता है)।

from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")

5

यदि हम print()फ़ंक्शन को देखें तो यह sys लाइब्रेरी का उपयोग किए बिना किया जा सकता है

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

यहाँ मेरा कोड है:

def update(n):
    for i in range(n):
        print("i:",i,sep='',end="\r",flush=True)
        #time.sleep(1)

5

मैंने यह कुछ समय पहले लिखा था और इससे वास्तव में खुश हूं। इसका इस्तेमाल करने के लिए स्वतंत्र महसूस करें।

यह एक लेता है indexऔर totalऔर वैकल्पिक रूप से titleया bar_length। एक बार हो जाने पर, घंटे के गिलास को एक चेक-मार्क से बदल दिया जाता है।

⏳ Calculating: [████░░░░░░░░░░░░░░░░░░░░░] 18.0% done

✅ Calculating: [█████████████████████████] 100.0% done

मैंने एक उदाहरण शामिल किया जो इसे परीक्षण करने के लिए चलाया जा सकता है।

import sys
import time

def print_percent_done(index, total, bar_len=50, title='Please wait'):
    '''
    index is expected to be 0 based index. 
    0 <= index < total
    '''
    percent_done = (index+1)/total*100
    percent_done = round(percent_done, 1)

    done = round(percent_done/(100/bar_len))
    togo = bar_len-done

    done_str = '█'*int(done)
    togo_str = '░'*int(togo)

    print(f'\t⏳{title}: [{done_str}{togo_str}] {percent_done}% done', end='\r')

    if round(percent_done) == 100:
        print('\t✅')


r = 50
for i in range(r):
    print_percent_done(i,r)
    time.sleep(.02)

shutil.get_terminal_size()यदि मेरी रुचि है, तो टर्मिनल चौड़ाई के आधार पर मेरे पास उत्तरदायी प्रगति पट्टी वाला एक संस्करण है ।


4

अरविंद वोगगु के उदाहरण में थोड़ी अधिक कार्यक्षमता जोड़ी :

def progressBar(name, value, endvalue, bar_length = 50, width = 20):
        percent = float(value) / endvalue
        arrow = '-' * int(round(percent*bar_length) - 1) + '>'
        spaces = ' ' * (bar_length - len(arrow))
        sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
                         name, width, arrow + spaces, int(round(percent*100))))
        sys.stdout.flush()
        if value == endvalue:     
             sys.stdout.write('\n\n')

अब आप पिछले एक की जगह के बिना कई प्रगतिबार उत्पन्न करने में सक्षम हैं।

मैंने nameएक निश्चित चौड़ाई के साथ एक मूल्य के रूप में भी जोड़ा है ।

दो छोरों और दो बार progressBar()परिणाम के उपयोग की तरह दिखेगा:

प्रगति बार एनीमेशन


-1

नीचे दिए गए कोड 0 से 137 तक संदेश की गिनती करेंगे, जो पिछले नंबर की जगह 0.3 सेकंड है।

बैकस्टेज के लिए प्रतीक की संख्या = अंकों की संख्या।

stream = sys.stdout
for i in range(137):
    stream.write('\b' * (len(str(i)) + 10))
    stream.write("Message : " + str(i))
    stream.flush()
    time.sleep(0.3)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.