2011-07-27 21 views
17

Sé que es posible reescribir constantemente la última línea que se muestra en el terminal con "\ r", pero tengo problemas para averiguar si hay una manera de volver atrás y editar líneas impresas en la consola.Python - Reescribe múltiples líneas en la consola

Lo que me gustaría hacer es reimprimir varias líneas para un juego de rol de texto, sin embargo, un amigo también se pregunta sobre esto para una aplicación que tiene una línea dedicada a una barra de progreso y otra que describe la descarga.

es decir, la consola imprimiría:

archivo de traslado: NameOfFile.txt
total Progreso: [########] 40%

y luego actualizar adecuadamente (para ambas líneas) como el programa se estaba ejecutando.

+1

¿En qué plataforma se supone que esto es en? –

+0

Unix, específicamente Fuduntu, pero me gustaría que funcione en la mayoría de las plataformas ... No es necesario. – JRJurman

+0

http://stackoverflow.com/questions/3002085/python-to-print-out-status-bar-and-percentage ¡buena respuesta, me ayudó muchísimo! –

Respuesta

28

En Unix, utilice el módulo curses.

En Windows, hay varias opciones:

ejemplo simple que utiliza maldiciones (Soy un total de maldiciones n00b):

import curses 
import time 

def report_progress(filename, progress): 
    """progress: 0-10""" 
    stdscr.addstr(0, 0, "Moving file: {0}".format(filename)) 
    stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress)) 
    stdscr.refresh() 

if __name__ == "__main__": 
    stdscr = curses.initscr() 
    curses.noecho() 
    curses.cbreak() 

    try: 
     for i in range(10): 
      report_progress("file_{0}.txt".format(i), i+1) 
      time.sleep(0.5) 
    finally: 
     curses.echo() 
     curses.nocbreak() 
     curses.endwin() 
+0

Gracias, agregué el enlace en la respuesta. ¿La API es como las maldiciones de Unix? – codeape

+1

En realidad, hay un módulo para hacer lo que quiera: [barra de progreso] [http://code.google.com/p/python-progressbar/] –

+0

Bueno, pero cómo mostrar las filas de estado no en la parte superior de la pantalla, sino en la parte inferior (en la siguiente línea después de la salida anterior). Quiero un efecto como con múltiples 'pv --name' en una tubería –

2

última instancia, si se quiere manipular la pantalla, es necesario utilizar las bibliotecas de sistema operativo subyacente, que normalmente será:

  • maldiciones (o los códigos de control de terminales subyacentes, como seguimiento de la terminfo/termcap database) en Linux o OSX
  • la API de la consola win32 en Windows.

La respuesta de @codeape ya le ofrece algunas de las muchas opciones si no le importa apegarse a un sistema operativo o si desea instalar bibliotecas de terceros en Windows.

Sin embargo, si quiere una solución multiplataforma que simplemente puede instalar, puede usar asciimatics. Como parte del desarrollo de este paquete, tuve que resolver las diferencias entre los entornos para proporcionar una única API que funciona en Linux, OSX y Windows.

Para barras de progreso, puede usar el objeto BarChart como se muestra en this demo usando this code.

+1

Estoy algo sorprendido de que algo así como útil como una manipulación de consola multiplataforma no se envía con Python. (Esp. Dada la existencia de Tkinter) – PythonNut

+1

@PythonNut - No conozco el historial completo, pero AFAIK nadie estaba preparado para escribir un soporte compatible con una API para Windows y entonces la [recomendación] (https: // docs. python.org/3/howto/curses.html) utilizará las diversas opciones de código de pegamento ya mencionadas. –

1

Aquí es un módulo de Python para ambos Python 2/3, lo que simplemente puede resolver esta situación con algunos línea de código; D

reprint - A simple module for Python 2/3 to print and refresh multi line output contents in terminal

Usted puede simplemente tratar de que output ejemplo como normales dict o list (depende del modo que use).Al modificar ese contenido en el output ejemplo, la salida de la terminal se actualizará automáticamente: D

Para su necesidad, aquí está el código:

from reprint import output 
import time 

if __name__ == "__main__": 
    with output(output_type='dict') as output_lines: 
     for i in range(10): 
      output_lines['Moving file'] = "File_{}".format(i) 
      for progress in range(100): 
       output_lines['Total Progress'] = "[{done}{padding}] {percent}%".format(
        done = "#" * int(progress/10), 
        padding = " " * (10 - int(progress/10)), 
        percent = progress 
        ) 
       time.sleep(0.05) 
+0

Cuando intento 'output_lines ['one'] = 'abcd'', después de configurarlo como lo hizo, obtengo un error de división cero. Creo que hay algo mal aquí. ¿Tienes alguna idea de eso? – cat40

+0

@ cat40 Creo que tal vez sea algo que haga que 'get_terminal_size()' devuelva un valor de (0,0). ¿Puedo pedir más detalles para eso? Puedes publicarlo en el número de Github: D – Yinzo

Cuestiones relacionadas