Bagaimana cara menulis output di tempat yang sama di konsol?

158

Saya baru mengenal python dan sedang menulis beberapa skrip untuk mengotomatisasi pengunduhan file dari server FTP, dll. Saya ingin menunjukkan progres pengunduhan, tetapi saya ingin tetap pada posisi yang sama, seperti:

keluaran:

Mengunduh File FooFile.txt [47%]

Saya mencoba menghindari sesuatu seperti ini:

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

Bagaimana saya harus melakukan ini?


Gandakan : Bagaimana saya bisa mencetak pada baris saat ini dalam aplikasi baris perintah?

scottm
sumber
1
Anda mungkin tertarik pada modul yang mudah digunakan ini, ini adalah bilah kemajuan teks. pypi.python.org/pypi/progressbar/2.2
wim

Jawaban:

254

Anda juga dapat menggunakan carriage return:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()
codelogic
sumber
13
Solusi yang sangat umum dan sederhana. Catatan: jika saluran Anda lebih panjang dari lebar terminal Anda, ini menjadi jelek.
ephemient
5
Saya juga harus menambahkan panggilan ke sys.stdout.flush () sehingga kursor tidak terpental sekitar
scottm
19
Apakah mungkin melakukan ini dengan beberapa baris? Katakanlah saya memiliki tiga unduhan berbeda, dan saya ingin menunjukkan kemajuan masing-masing pada jalurnya sendiri.
EarlCrapstone
11
Saya suka meletakkan \rdi awal baris, dan menambahkan \x1b[Kuntuk menghapus teks sebelumnya.
augurar
11
Sepertinya solusi paling sederhana untuk python 3 (seperti yang disebutkan dalam jawaban di bawah) adalah: print("sample text", end='\r", flush=True)
Cyrus
35

Python 2

Saya suka yang berikut ini:

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

Demo:

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

Demo:

import time

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

PyCharm Debugger Console dengan 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.')
RSabet
sumber
9
gunakan ini untuk python 3+: print ('Mengunduh File FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha
Di konsol PyCharm Debugger, harus ada sebelum teks. Jika tidak, teks mungkin tidak muncul sama sekali, atau muncul tidak konsisten. Saya menambahkan versi yang berfungsi untuk saya sebagai edit, karena saya tidak bisa menulis kode multi-baris dalam jawaban ini. Saya meletakkannya di intisari saya sehingga orang-orang dapat melihatnya saat suntingan sedang menunggu persetujuan: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Yul Kang
"\ r" di akhir string berfungsi untuk saya di konsol debugger di PyCharm 2020.1 (PyCharm 2020.1.2 (Edisi Komunitas); Build # PC-201.7846.77, dibangun pada 31 Mei 2020).
bertempurlah
28

Gunakan perpustakaan penanganan terminal seperti modul kutukan :

Modul kutukan menyediakan antarmuka ke perpustakaan kutukan, standar de-facto untuk penanganan terminal canggih portabel.

Gimel
sumber
1
Tidak tersedia untuk Windows.
Diego Herranz
3
@Diego sekarang ada perpustakaan dukungan untuk modul kutukan pada Windows. lihat stackoverflow.com/a/19851287/1426237
Plexico
15

Cetak karakter backspace \bbeberapa kali, dan kemudian timpa nomor lama dengan nomor baru.

Zach Scrivena
sumber
menarik, saya tidak berpikir untuk melakukannya dengan cara itu.
Chris Ballance
Saya suka ini karena tidak menghapus perintah sebelumnya (jika Anda memiliki beberapa tahapan yang ingin Anda tinggalkan di layar)
Nathan Donnellan
3
Menggunakan carriage return (mis. print 'Downloading.... \r') Juga tidak menghapus data sebelumnya, tetapi mencegah harus mengetahui seberapa jauh cadangannya.
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="")
Christian Calderon
sumber
Mengapa ini lebih baik daripada yang di atas (saya adalah Python n00b, jadi tolong permisi ketidaktahuan saya :-))?
BalinKingOfMoria Reinstate CMs
7

Untuk Python 3xx:

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

Solusi rapi yang telah bekerja untuk saya adalah:

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

The sys.stdout.flushpenting jika tidak akan benar-benar kikuk dan print("")pada loop keluar juga penting.

UPDATE : Seperti yang disebutkan dalam komentar, printjuga memiliki flushargumen. Jadi yang berikut ini juga akan berfungsi:

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("")
Michael Hall
sumber
1
Dalam Python modern, Anda bisa menyediakan argumen flush=Trueuntuk print, jadi tidak perlu untuk sys.stdout.flush()panggilan ekstra .
PM 2Ring
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="")
Hazarika Melayu
sumber