Pregunta

Tengo una aplicación basada en Python que puede aceptar algunos comandos en un simple read-eval-print-loop. Estoy usando raw_input ('>') para obtener la entrada. En los sistemas basados ??en Unix, también import readline para que las cosas se comporten un poco mejor. Todo esto está funcionando bien.

El problema es que hay eventos asincrónicos entrantes y me gustaría imprimir la salida tan pronto como sucedan. Desafortunadamente, esto hace que las cosas se vean feas. El " > " la cadena no aparece nuevamente después de la salida, y si el usuario está a mitad de escribir algo, corta su texto por la mitad. Probablemente debería volver a dibujar el texto en progreso del usuario después de imprimir algo.

Esto parece ser un problema resuelto. ¿Cuál es la forma correcta de hacer esto?

También tenga en cuenta que algunos de mis usuarios están basados ??en Windows.

TIA

Editar: la respuesta aceptada funciona en plataformas Unixy (cuando el módulo readline está disponible), pero si alguien sabe cómo hacer que esto funcione en Windows, ¡sería muy apreciado!

¿Fue útil?

Solución

Tal vez algo como esto haga el truco:

#!/usr/bin/env python2.6

from __future__ import print_function

import readline
import threading

PROMPT = '> '

def interrupt():
    print() # Don't want to end up on the same line the user is typing on.
    print('Interrupting cow -- moo!')
    print(PROMPT, readline.get_line_buffer(), sep='', end='')

def cli():
    while True:
        cli = str(raw_input(PROMPT))

if __name__ == '__main__':
    threading.Thread(target=cli).start()
    threading.Timer(2, interrupt).start()

No creo que stdin sea seguro para subprocesos, por lo que puede terminar perdiendo caracteres en el subproceso de interrupción (que el usuario tendrá que volver a escribir al final de interrupt ). Exageré la cantidad de tiempo interrupt con la llamada time.sleep . La llamada readline.get_line_buffer no mostrará los caracteres que se pierden, por lo que todo saldrá bien.

Tenga en cuenta que stdout en sí mismo no es seguro para subprocesos, por lo que si tiene varios subprocesos de ejecución interrumpidos, esto puede terminar pareciendo asqueroso.

Otros consejos

¿Por qué estás escribiendo tu propio REPL usando raw_input () ? ¿Has mirado la clase cmd.Cmd ? Editar: acabo de encontrar la sclapp , que también puede ser útil.

Nota: la clase cmd.Cmd (y sclapp) puede o no admitir directamente su objetivo original; es posible que deba subclasificarlo y modificarlo según sea necesario para proporcionar esa función.

ejecuta esto:

python -m twisted.conch.stdio

Obtendrá un REPL agradable, coloreado y asíncrono, sin usar hilos . Mientras escribe en el indicador, el bucle de eventos se está ejecutando.

mire el módulo de código, le permite crear objetos para interpretar también el código de Python (conector descarado) https: // github.com/iridium172/PyTerm le permite crear programas de línea de comandos interactivos que manejan la entrada de teclado sin formato (como ^ C generará un KeyboardInterrupt).

Es una especie de no respuesta, pero miraría el código de IPython para mira cómo lo están haciendo.

Creo que tienes 2 opciones básicas:

  1. Sincronice su salida (es decir, bloquee hasta que vuelva)
  2. Separe su entrada y su salida (asíncrona), tal vez en dos columnas separadas.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top