ฉันจะเขียนเอาต์พุตในตำแหน่งเดียวกันบนคอนโซลได้อย่างไร


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
เป็นไปได้ไหมที่จะทำเช่นนี้กับหลายบรรทัด? ให้บอกว่าฉันมีการดาวน์โหลดต่างกันสามครั้งและฉันต้องการแสดงความคืบหน้าของแต่ละรายการในสายของตัวเอง
EarlCrapstone

11
ฉันชอบที่จะวาง\rที่จุดเริ่มต้นของบรรทัดและเพิ่ม\x1b[Kเพื่อล้างข้อความก่อนหน้า
augurar

11
ดูเหมือนว่าการแก้ปัญหาที่ง่ายที่สุดสำหรับหลาม 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="")

PyCharm Debugger Console พร้อม Python 3

# 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 ('การดาวน์โหลดไฟล์ FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha

บน PyCharm Debugger console \ r ต้องมาก่อนข้อความ มิฉะนั้นข้อความอาจไม่ปรากฏขึ้นเลยหรือปรากฏอย่างไม่สอดคล้องกัน ฉันเพิ่มเวอร์ชันที่ใช้งานได้สำหรับฉันเนื่องจากฉันไม่สามารถเขียนโค้ดหลายบรรทัดในคำตอบนี้ ฉันวางมันลงในส่วนสำคัญของฉันเพื่อให้ผู้คนสามารถดูได้ในขณะที่การแก้ไขกำลังรอการอนุมัติ: gist.github.com/yulkang/40168c7729a7a7a7b96d0116d8b1bc26df
Yul Kang

"\ r" ที่ส่วนท้ายของสตริงใช้งานได้สำหรับฉันในคอนโซลดีบักเกอร์บน PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); Build # PC-201.7846.77 ซึ่งสร้างขึ้นเมื่อวันที่ 31 พฤษภาคม 2020)
battey

28

ใช้ไลบรารีจัดการเทอร์มินัลเช่นโมดูล curses :

โมดูล curses จัดเตรียมอินเตอร์เฟสไปยังไลบรารี curses ซึ่งเป็นมาตรฐาน de-facto สำหรับการจัดการเทอร์มินัลขั้นสูงแบบพกพา


1
ไม่พร้อมใช้งานสำหรับ Windows
Diego Herranz

3
@Diego ตอนนี้มีไลบรารีสนับสนุนสำหรับโมดูล curses บน Windows ดูstackoverflow.com/a/19851287/1426237
Plexico

15

พิมพ์อักขระถอยกลับ\bหลาย ๆ ครั้งจากนั้นเขียนทับหมายเลขเดิมด้วยหมายเลขใหม่


น่าสนใจฉันไม่เคยคิดที่จะทำแบบนั้น
Chris Ballance

ฉันชอบสิ่งนี้เพราะมันไม่ชัดเจนคำสั่งก่อนหน้า (ถ้าคุณมีหลายขั้นตอนที่คุณต้องการออกจากหน้าจอ)
นาธาน Donnellan

3
การใช้ carriage return (เช่นprint 'Downloading.... \r') ยังไม่ได้ล้างข้อมูลก่อนหน้า แต่ก็ป้องกันไม่ให้ต้องทราบว่าจะต้องสำรองข้อมูลนานแค่ไหน
cod3monk3y

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

ทำไมสิ่งนี้ถึงดีกว่าข้างต้น (ฉันเป็นงูหลาม n00b ดังนั้นโปรดแก้ตัวด้วยความไม่รู้ :-))?
BalinKingOfMoria คืนสถานะ CM ใหม่


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เป็นสิ่งสำคัญมิฉะนั้นจะได้รับ clunky จริงๆและprint("")ในห่วงทางออกยังเป็นสิ่งสำคัญ

ปรับปรุง : ตามที่กล่าวไว้ในความคิดเห็น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
ในปัจจุบันงูหลามคุณสามารถจัดหาหาเรื่องของflush=Trueการprintจึงมีความจำเป็นในการเสริมsys.stdout.flush()โทร
PM 2Ring

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.