【问题标题】:How can I overwrite/print over the current line in Windows command line?如何在 Windows 命令行中覆盖/打印当前行?
【发布时间】:2021-10-24 09:42:10
【问题描述】:

在 Unix 上,我可以使用 \r(回车)或 \b(退格)覆盖 shell 中的当前行(打印已经可见的文本)。

我可以通过 Python 脚本在 Windows 命令行中实现相同的效果吗?

我尝试了 curses 模块,但它似乎在 Windows 上不可用。

【问题讨论】:

  • 我的question 关于 Python 下载进度指示器可能会有所帮助。

标签: python windows command-line overwrite carriage-return


【解决方案1】:

在 PyCharm 2020.3 和 Python 3.9 版上测试,为了覆盖书面打印输出,我使用以下内容:

from time import sleep

for x in range(10):
    print(f'\r {x}', end='')
    sleep(0.6)

这是我主要用于我的程序的代码。使用 end='\r' 将为我覆盖整个文本,忽略睡眠。

在实际场景中,我是这样设置的:

    def progress_callback(progress):
        print(f'\rDownloading File: {progress.dlable.file_name}  Progress: ' + '{0:.2f}%'.format(progress.percent), end='')
        # `return True` if the download should be canceled
        return False

    print('\nDownload complete!)

覆盖功能后的打印必须换行,否则之前的同一行将被覆盖。

【讨论】:

    【解决方案2】:

    简单的方法:

    import sys
    from time import sleep
    import os
    
    #print("\033[y coordinate;[x coordinateH Hello")
    os.system('cls')
    sleep(0.2)
    print("\033[1;1H[]")
    sleep(0.2)
    print("\033[1;1H  []")
    sleep(0.2)
    print("\033[1;1H    []")
    sleep(0.2)
    print("\033[1;1H      []")
    sleep(0.2)
    print("\033[1;1H        []")
    sleep(0.2)
    print("\033[1;1H      []")
    sleep(0.2)
    print("\033[1;1H    []")
    sleep(0.2)
    print("\033[1;1H  []")
    sleep(0.2)
    print("\033[1;1H[]")
    sleep(0.2)
    

    【讨论】:

      【解决方案3】:

      是的,这个问题是 11 年前提出的,但很酷。我喜欢即兴创作。 附加到 nosklo 的答案:

      import sys
      import time
      
      def restart_line():
          sys.stdout.write("\r")
          sys.stdout.flush()
      
      string_one = "some data that is very long..."
      sys.stdout.write(string_one)
      sys.stdout.flush()
      
      time.sleep(2)
      restart_line()
      
      string_two = "shorter data"
      if len(string_two) < len(string_one):
          string_two = string_two+(" "*int((len(string_one)-len(string_two))))
          # This will overwrite the characters that would be left on the console
      
      sys.stdout.write(string_two)
      sys.stdout.flush()
      

      【讨论】:

        【解决方案4】:

        最简单的方法是使用两个 \r - 一个在开头,一个在结尾

        for i in range(10000):
            print('\r'+str(round(i*100/10000))+'%  Complete\r'),
        

        很快就会过去的

        【讨论】:

        • :-/ 第一个\r 将被处理9999 次无效。如果不知道光标在哪里,可以在循环前调用print('\r')once
        【解决方案5】:

        感谢这里所有有用的答案。我需要这个:)

        我发现 nosklo 的答案特别有用,但我希望通过将所需的输出作为参数传递来完全包含在函数中。另外,我真的不需要计时器,因为我希望在特定事件之后进行打印)。

        这就是我的诀窍,我希望其他人觉得它有用:

        import sys
        
        def replace_cmd_line(output):
            """Replace the last command line output with the given output."""
            sys.stdout.write(output)
            sys.stdout.flush()
            sys.stdout.write('\r')
            sys.stdout.flush()
        

        【讨论】:

        • 最后只需要一个flush()。我不确定sys.stdout.write(output + '\r') 会比两个方法调用快得多(因为为字符串分配内存、复制、GC),所以将它们分开可能是可以的。
        【解决方案6】:
        import sys 
        import time
        
        for i in range(10):
            print '\r',         # print is Ok, and comma is needed.
            time.sleep(0.3)
            print i,
            sys.stdout.flush()  # flush is needed.
        

        如果在 IPython-notebook 上,就像这样:

        import time
        from IPython.display import clear_output
        
        for i in range(10):
            time.sleep(0.25)
            print(i)
            clear_output(wait=True)
        

        http://nbviewer.ipython.org/github/ipython/ipython/blob/master/examples/notebooks/Animations%20Using%20clear_output.ipynb

        【讨论】:

        • ipython notebook/jupyter 就是我要找的!
        【解决方案7】:

        我刚遇到这个问题。您仍然可以使用\r,即使在 Windows 命令提示符中,但它只会带您回到上一个换行符 (\n)。

        如果你这样做:

        cnt = 0
        print str(cnt)
        while True:
            cnt += 1
            print "\r" + str(cnt)
        

        你会得到:

        0
        1
        2
        3
        4
        5
        ...
        

        那是因为\r 只会回到最后一行。由于您已经使用最后一个打印语句编写了换行符,因此您的光标将从新空行的开头移动到同一新空行的开头。

        为了说明,打印第一个 0 后,您的光标将在此处:

        0
        | # <-- Cursor
        

        当您\r 时,您会转到行首。但是你已经在行首了。

        解决方法是避免打印\n 字符,因此您的光标位于同一行,\r 会正确覆盖文本。你可以通过print 'text', 做到这一点。逗号可防止打印换行符。

        cnt = 0
        print str(cnt),
        while True:
            cnt += 1
            print "\r" + str(cnt),
        

        现在它将正确地重写行。

        请注意,这是 Python 2.7,因此是 print 语句。

        【讨论】:

        • 换行避免完全解决了我的问题,谢谢!作为补充,在 Python 3 中可以使用 print(msg, end=' ') 来避免换行。
        【解决方案8】:

        我知道这是旧的,但我想告诉我的版本(它可以在我的电脑上的 cmd 中工作,但不能在空闲时)覆盖 Python 3 中的一行:

        >>> from time import sleep
        >>> for i in range(400):
        >>>     print("\r" + str(i), end="")
        >>>     sleep(0.5)
        

        编辑: 它适用于 Windows 和 Ubuntu

        【讨论】:

        • 统计Mac OS in
        • 仍然没有解决 IDLE 的问题?
        【解决方案9】:

        是的:

        import sys
        import time
        
        def restart_line():
            sys.stdout.write('\r')
            sys.stdout.flush()
        
        sys.stdout.write('some data')
        sys.stdout.flush()
        time.sleep(2) # wait 2 seconds...
        restart_line()
        sys.stdout.write('other different data')
        sys.stdout.flush()
        

        【讨论】:

        • 如果第二个数据比第一个短,第一个数据的字符会留在控制台
        【解决方案10】:

        在 Windows (python 3) 上,它似乎可以工作(不直接使用 stdout):

        import sys
        
        for i in reversed(range(0,20)):
          time.sleep(0.1)
          if(i == 19):
            print(str(i), end='', file=sys.stdout)
          else:
            print("\r{0:{width}".format(str(i), width = w, fill = ' ', align = 'right'), end='', file=sys.stdout)
          sys.stdout.flush()
          w = len(str(i))
        

        每次调用 print 函数时都会更新同一行。

        此算法可以改进,但发布它是为了展示您可以做什么。您可以根据需要修改方法。

        【讨论】:

        • 这不起作用,因为您在调用它之后定义了w
        【解决方案11】:

        如果您只想更新上一​​行,那么简单的方法:

        import time
        for i in range(20):
            print str(i) + '\r',
            time.sleep(1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-08
          • 1970-01-01
          • 2014-04-10
          • 2012-12-02
          • 1970-01-01
          相关资源
          最近更新 更多