2011-02-04 7 views
53

Tôi đang viết một trình tải xuống ftp đơn giản. Một phần của mã là một cái gì đó như thế này:đầu ra cho cùng một dòng ghi đè đầu ra trước đó? python (2.5)

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

tôi đang kêu gọi quá trình chức năng để xử lý các cuộc gọi lại:

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

và đầu ra là một cái gì đó như thế này:

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

nhưng tôi muốn in dòng này và lần sau in lại/làm mới nó để nó chỉ hiển thị một lần và tôi sẽ thấy tiến trình tải xuống đó ...

Làm thế nào nó có thể được thực hiện?

Trả lời

95

Dưới đây là mã cho Python 3.x:

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

Từ khóa end= là những gì hiện công việc ở đây - theo mặc định, print() kết thúc bằng một newline (\n) ký tự, nhưng điều này có thể được thay thế bằng một chuỗi khác nhau. Trong trường hợp này, kết thúc dòng có trả về vận chuyển thay vì trả về con trỏ đến đầu dòng hiện tại. Do đó, không cần nhập mô-đun sys cho loại sử dụng đơn giản này. print() thực sự có a number of keyword arguments có thể được sử dụng để đơn giản hóa mã.

Để sử dụng cùng mã trên Python 2.6+, đặt dòng sau ở phía trên cùng của tập tin:

from __future__ import print_function 
+6

Lưu ý rằng chức năng in cũng có thể được sử dụng trong python 2.6+ bằng cách thêm nhập sau đây ở đầu tệp: 'from __future__ import print_function'. – janin

+11

trong python <3.0 một dấu phẩy ở cuối câu lệnh sẽ ngăn chặn một "\ n": 'print" foo ",' Tuy nhiên bạn vẫn cần tuôn ra sau đó để xem thay đổi: 'sys.stdout.flush() ' –

+9

Tôi thấy rằng tôi cần phải bao gồm' \ r' ở đầu chuỗi và đặt 'end = ''' để làm việc này. Tôi không nghĩ thiết bị đầu cuối của tôi thích nó khi tôi kết thúc bằng '\ r' – Jezzamon

14

Hãy xem curses module documentationcurses module HOWTO.

dụ Thật cơ bản:

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

thật không may, lời nguyền chỉ có sẵn trên Unix.OP không cho chúng tôi biết hệ điều hành nào mà ứng dụng của anh ta đang nhắm mục tiêu ... –

+2

Tôi cần nó cho Windows – Kristian

+0

Tôi rất quen với việc làm việc dưới Linux mà thậm chí tôi không nhận thấy cảnh báo về mô-đun chỉ dành cho UNIX trong tài liệu mô-đun .. Cảm ơn bạn đã chỉ ra điều đó, @Adrien. –

32

Nếu tất cả các bạn muốn làm là thay đổi một dòng duy nhất, sử dụng \r. \r có nghĩa là vận chuyển trở lại. Đó là hiệu ứng là chỉ để đặt dấu mũ ở đầu dòng hiện tại. Nó không xóa bất cứ thứ gì. Tương tự, \b có thể được sử dụng để đi ngược lại một ký tự. (Một số thiết bị đầu cuối có thể không hỗ trợ tất cả những tính năng)

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

tôi sẽ thêm rằng '\ r' có nghĩa là vận chuyển trở lại. hiệu ứng của nó là chỉ để đặt dấu mũ ở đầu dòng hiện tại. nó không xóa bất cứ thứ gì. tương tự, '\ b' có thể được sử dụng để đi ngược lại một ký tự. (một số thiết bị đầu cuối có thể không hỗ trợ tất cả các tính năng đó) –

+0

'sys.stdout.write ('% s \ r', size_str ')' tôi nghĩ bạn có nghĩa là 'sys.stdout.write ('% s \ r '% size_str)' nhưng nó không hoạt động. – Kristian

+0

với sửa chữa đó tôi đã viết nó HOẠT ĐỘNG ;-), cảm ơn – Kristian

9

Đây là lớp học nhỏ của tôi có thể in lại khối văn bản. Nó đúng xóa các văn bản trước đó, do đó bạn có thể ghi đè lên văn bản cũ của bạn với văn bản mới ngắn hơn mà không cần tạo ra một mớ hỗn độn.

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") 
+1

Điều này sẽ không hoạt động trong Windows lên đến Windows 10, vì Windows 10 là cửa sổ đầu tiên hỗ trợ các ký tự điều khiển này https://en.wikipedia.org/wiki/ANSI_escape_code – user136036

5

tôi thấy rằng đối với một tuyên bố in đơn giản trong python 2.7, chỉ cần đặt một dấu phẩy ở cuối sau '\r' của bạn.

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

Đây là ngắn hơn các giải pháp không phải python 3 khác, nhưng cũng khó duy trì hơn.

+0

Python 2.7.10 và nó không in bất cứ thứ gì . Có lẽ, bạn có thể biên dịch nó trực tuyến và gửi cho chúng tôi một liên kết để xem nó hoạt động như thế nào ...? –

3

Bạn chỉ có thể thêm '\ r' ở cuối chuỗi cộng với dấu phẩy ở cuối chức năng in. Ví dụ:

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

Điều này là dành cho python 3? Nếu vậy, những gì với tham số 'end' mặc định được đặt thành' \ n' để u in '(...) KB được tải xuống! \ R \ n'. Liệu tôi có sai? –