Đầu ra đến cùng một dòng ghi đè đầu ra trước đó?


94

Tôi đang viết trình tải xuống FTP. Một phần của mã là một cái gì đó như thế này:

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

Tôi đang gọi quy trình hàm để xử lý lệnh 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 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 đó.

Nó được hoàn thiện bằng cách nào?



Câu trả lời:


185

Đây là mã cho Python 3.x:

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

Các end=từ khóa là những gì hiện công việc ở đây - theo mặc định, print()kết thúc trong một dòng mới ( \nký 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 bằng ký tự xuống dòng thay vì trả lại con trỏ về đầu dòng hiện tại. Do đó, không cần phải nhập sysmô-đun cho kiểu sử dụng đơn giản này. print()thực sự có một số đối số từ khóa có thể được sử dụng để đơn giản hóa mã.

Để sử dụng cùng một mã trên Python 2.6+, hãy đặt dòng sau ở đầu tệp:

from __future__ import print_function

6
Lưu ý rằng các chức năng in cũng có thể được sử dụng trong python 2.6+ bằng cách thêm việc nhập khẩu sau ở phía trên cùng của tập tin: from __future__ import print_function.
janin

12
trong python <3.0 một dấu phẩy ở phần cuối của bản tuyên bố sẽ ngăn chặn một "\ n": print "foo",Tuy nhiên bạn vẫn cần phải tuôn ra sau đó để thấy sự thay đổi:sys.stdout.flush()
Tobias Domhan

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

2
Trong tất cả các bản phát hành Python 3 hiện tại, bạn có thể thêm flush=Truevào print()hàm để đảm bảo bộ đệm được xóa (bộ đệm dòng tiêu chuẩn chỉ được xóa khi \ndòng mới được viết).
Martijn Pieters

4
Trong một máy tính xách tay jupyter, sử dụng \rngay từ đầu và end=''hoạt động tốt nhất và mượt mà nhất. Sử dụng flush=Truevới \rở cuối nếu chuỗi và end='\r'cũng hoạt động nhưng không trơn tru & xóa dòng & nguồn cấp dữ liệu của nó.
Dave X

40

Nếu tất cả những gì bạn muốn làm là thay đổi một dòng, hãy sử dụng \r. \rnghĩa là xuống dòng. Nó chỉ có tác dụng là đặt dấu mũ trở lại đầu dòng hiện tại. Nó không xóa bất cứ điều gì. Tương tự, \bcó thể được sử dụng để 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 đó)

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 điều đó \rcó nghĩa là ký tự xuống dòng. tác dụng của nó chỉ là đặt dấu mũ trở lại đầu dòng hiện tại. nó không xóa bất cứ điều gì. tương tự, \bcó thể được sử dụng để 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)
Adrien Plisson

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

@Adrien: Hay quá, đã thêm vào đó. @Kristian: Cảm ơn, đã cập nhật thông tin đó, khá muộn.
Sam Dolan

Cũng lưu ý rằng bạn vẫn có thể sử dụng printthay vì sys.stdout.writenếu bạn thích: print size_str + "\r",hoạt động tốt. Ở ,cuối câu lệnh in sẽ ngăn dòng mới; sys.stdout.flush()vẫn cần thiết
Jeff

19

Hãy xem tài liệu mô-đun lời nguyềnmô-đun lời nguyền HOWTO .

Ví dụ thực sự 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()

10
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 ứng dụng mình đang nhắm mục tiêu ...
Adrien Plisson

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

3
@AdrienPlisson, tôi biết rằng câu hỏi này đã được thực hiện năm trước nhưng, bạn thực sự có thể nhận được lời nguyền lên Windows: lfd.uci.edu/~gohlke/pythonlibs/#curses
Lạnh diamondZ

Khi tôi dán đoạn mã này vào trình thông dịch Python của mình, thiết bị đầu cuối của tôi đã trở thành trang bị lỗi. Thoát khỏi trình thông dịch không giúp được gì. WTF ?!
mã allyourcode

Sử dụng clrtoeolcho khi dòng thứ hai là ngắn hơn so với người đầu tiên.
Serge Stroobandt,

9

Đây là lớp học nhỏ của tôi có thể in lại các khối văn bản. Nó xóa đúng cách văn bản trước đó để bạn có thể ghi đè văn bản cũ của mình bằng văn bản mới ngắn hơn mà không 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")

2
Điều này sẽ không làm việc trong Windows lên đến Windows 10, Windows 10 vì là cửa sổ đầu tiên để hỗ trợ những ký tự điều khiển en.wikipedia.org/wiki/ANSI_escape_code
user136036

8

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

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

Điều này ngắn hơn so với 3 giải pháp không phải python khác, nhưng cũng khó bảo trì hơn.


1
Python 2.7.10 và nó không in bất cứ thứ gì. Có thể, 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 ...?
Shougo Makishima

5

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

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

1
Đây là dành cho python 3? Nếu vậy những gì với endtham số mặc định được đặt thành \nu in (...)KB downloaded!\r\n. Liệu tôi có sai?
SR

Sử dụng end = '\r'thay vì sửa chữa vấn đề bằng Python 3.
Abhimanyu Pallavi Sudhir

4

Tôi đang sử dụng spyder 3.3.1 - windows 7 - python 3.6 mặc dù có thể không cần xả. dựa trên bài đăng này - https://github.com/spyder-ide/spyder/issues/3437

   #works in spyder ipython console - \r at start of string , end=""
import time
import sys
    for i in range(20):
        time.sleep(0.5)
        print(f"\rnumber{i}",end="")
        sys.stdout.flush()

1

để ghi đè dòng trước đó trong python, tất cả những gì bạn cần là thêm end = '\ r' vào hàm in, hãy kiểm tra ví dụ này:

import time
for j in range(1,5):
   print('waiting : '+j, end='\r')
   time.sleep(1)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.