Pergunta

Eu tenho um aplicativo baseado em Python que pode aceitar alguns comandos em uma simples leitura eval-print-loop. Estou usando raw_input('> ') para obter a entrada. Em sistemas baseados em Unix, eu também import readline para tornar as coisas se comportam um pouco melhor. Tudo bem que isso está funcionando.

O problema é que existem eventos assíncronos chegando, e eu gostaria de imprimir a saída assim que eles acontecem. Infelizmente, isso torna as coisas olhar feio. A ">" string não aparecer novamente após a saída, e se o usuário estiver no meio de digitação algo, ele corta o seu texto no meio. Provavelmente deve redesenhar texto-in-progress do usuário depois de imprimir algo.

Isto parece que deve ser um problema resolvido. Qual é a maneira correta de fazer isso?

Observe também que alguns dos meus usuários são baseados em Windows.

TIA

Editar: A resposta aceitos trabalhos em plataformas UNIXy (quando o módulo readline estiver disponível), mas se alguém sabe como fazer este trabalho no Windows, isso seria muito apreciado

Foi útil?

Solução

Talvez algo como isso irá fazer o truque:

#!/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()

Eu não acho que stdin é thread-safe, então você pode acabar perdendo caracteres para o segmento de interrupção (que o usuário terá que digitar novamente no final do interrupt). I exagerada a quantidade de tempo interrupt com a chamada time.sleep. A chamada readline.get_line_buffer não vai exibir os caracteres que se perdem, assim tudo acaba bem.

Note que stdout em si não é thread-safe, então se você tem múltiplos interrompendo threads de execução, isso ainda pode acabar procurando bruta.

Outras dicas

Por que você está escrevendo seu próprio REPL usando raw_input()? Você já olhou para a classe cmd.Cmd? Editar: Eu só descobri a biblioteca sclapp , que também pode ser útil.

Nota: a classe cmd.Cmd (e sclapp) pode ou não pode apoiar diretamente seu objetivo original; você pode ter que subclasse-lo e modificá-lo conforme necessário para fornecer esse recurso.

executar este:

python -m twisted.conch.stdio

Você vai ter uma agradável, colorido, assíncrona REPL, sem o uso de fios . Enquanto você digita no prompt, o ciclo de eventos está em execução.

olhar para o módulo de código, que permite criar objetos para interpretar código python também (plug descarado) https: // github.com/iridium172/PyTerm permite criar programas de linha de comando interativas que lidam com a entrada do teclado crua (como ^ C vai levantar uma KeyboardInterrupt).

É uma espécie de um não-resposta, mas eu ficaria em IPython de código para ver como eles estão fazendo isso.

Eu acho que você tem 2 opções básicas:

  1. Sincronizar sua saída (bloco ou seja, até que ele volta)
  2. Separar sua entrada e sua saída (asyncronous), talvez em duas colunas separadas.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top