【问题标题】:Output to the same line overwriting previous output?输出到同一行覆盖以前的输出?
【发布时间】:2023-03-17 02:50:01
【问题描述】:

我正在编写一个 FTP 下载器。部分代码是这样的:

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

我正在调用函数进程来处理回调:

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

输出是这样的:

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

但我希望它打印这一行并下次重新打印/刷新它,这样它只会显示一次,我会看到下载的进度。

怎么做?

【问题讨论】:

标签: python refresh progress-bar


【解决方案1】:

这是 Python 3.x 的代码:

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

end= 关键字在这里起作用——默认情况下,print() 以换行符 (\n) 结尾,但可以用不同的字符串替换。在这种情况下,以回车结束行,而是将光标返回到当前行的开头。因此,对于这种简单的用法,无需导入 sys 模块。 print() 实际上有 a number of keyword arguments 可以用来大大简化代码。

要在 Python 2.6+ 上使用相同的代码,请将以下行放在文件顶部:

from __future__ import print_function

【讨论】:

  • 请注意,通过在文件顶部添加以下导入,打印功能也可以在 python 2.6+ 中使用:from __future__ import print_function
  • 在 python print "foo", 但是您仍然需要在此之后刷新才能看到更改:sys.stdout.flush()
  • 我发现我需要在字符串的开头包含\r,并设置end='' 以使其正常工作。当我以 \r 结尾时,我认为我的终端不喜欢它
  • 在所有当前的 Python 3 版本中,您可以将 flush=True 添加到 print() 函数以确保刷新缓冲区(标准行缓冲区仅在写入 \n 换行符时才会刷新) .
  • 在 jupyter notebook 中,在开头使用 \rend='' 效果最好、最流畅。如果字符串和end='\r' 也有效但不平滑,则在末尾使用flush=True\r,并删除该行及其换行符。
【解决方案2】:

如果您只想更改一行,请使用\r\r 表示回车。它的作用只是将插入符号放回当前行的开头。它不会删除任何东西。同样,\b 可用于后退一个字符。 (某些终端可能不支持所有这些功能)

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)

【讨论】:

  • 我要补充一点,\r 表示回车。它的作用只是将插入符号放回当前行的开头。它不会删除任何东西。同样,\b 可用于后退一个字符。 (某些终端可能不支持所有这些功能)
  • sys.stdout.write('%s\r', size_str') 我想你的意思是sys.stdout.write('%s\r' % size_str) 但它不起作用。
  • @Adrien:酷,补充说。 @Kristian:谢谢,更新了,已经很晚了。
  • 另外请注意,如果您愿意,您仍然可以使用print 而不是sys.stdout.writeprint size_str + "\r", 工作正常。 print 语句末尾的, 禁止换行; sys.stdout.flush() 仍然需要
【解决方案3】:

看看curses module documentationcurses module HOWTO

非常基本的例子:

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

【讨论】:

  • 不幸的是,curses 仅在 Unix 上可用。 OP 没有告诉我们他的应用程序针对的是哪个操作系统...
  • 我已经习惯了在 Linux 下工作,以至于我什至没有注意到模块文档中关于该模块仅适用于 UNIX 的警告。感谢@Adrien 指出这一点。跨度>
  • @AdrienPlisson,我知道这个问题是几年前提出的,但是您实际上可以在 Windows 上获取 Curses:lfd.uci.edu/~gohlke/pythonlibs/#curses
  • 当我将它粘贴到我的 Python 解释器中时,我的终端变成了 fubar。退出解释器并没有帮助。 WTF?!
  • 当第二行比第一行短时,使用clrtoeol
【解决方案4】:

这是我的小班,可以重印文本块。它会正确清除以前的文本,因此您可以用较短的新文本覆盖旧文本,而不会造成混乱。

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

【讨论】:

【解决方案5】:

我发现对于 python 2.7 中的简单打印语句,只需在您的'\r' 后面加一个逗号即可。

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

这比其他非 python 3 解决方案更短,但也更难维护。

【讨论】:

  • Python 2.7.10,它没有打印任何东西。也许,您可以在线编译它并给我们发送一个链接,看看它是如何工作的......?
【解决方案6】:

我正在使用 spyder 3.3.1 - windows 7 - python 3.6 尽管可能不需要冲洗。 基于此帖子 - 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()

【讨论】:

    【解决方案7】:

    要覆盖 python 中的前一行,您只需将 end='\r' 添加到打印函数中,测试以下示例:

    import time
    for j in range(1,5):
       print('waiting : '+j, end='\r')
       time.sleep(1)
    

    【讨论】:

    • 完美运行。谢谢
    【解决方案8】:

    您可以在字符串末尾添加“\r”,并在打印函数末尾添加逗号。例如:

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

    【讨论】:

    • 这是为 python 3 准备的?如果是这样,默认的end 参数设置为\n,所以你打印(...)KB downloaded!\r\n。我错了吗?
    • 使用end = '\r' 来解决 Python 3 中的问题。
    猜你喜欢
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 2016-02-02
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多