Подтвердить что ты не робот

Как реализовать python REPL, который прекрасно обрабатывает асинхронный вывод?

У меня есть приложение на основе Python, которое может принимать несколько команд в простом цикле чтения-eval-print. Я использую raw_input('> ') для ввода. В системах на базе Unix я также import readline, чтобы все выглядело немного лучше. Все это прекрасно работает.

Проблема в том, что происходят асинхронные события, и я хотел бы печатать выходные данные, как только они произойдут. К сожалению, это заставляет вещи выглядеть уродливыми. Строка " > " не появляется снова после выхода, и если пользователь находится на полпути, набрав что-то, он прерывает их текст пополам. Вероятно, он должен перерисовать текст пользователя в процессе после печати. ​​

Кажется, что это должна быть проблема. Каков правильный способ сделать это?

Также обратите внимание, что некоторые из моих пользователей основаны на Windows.

ТИА

Изменить: принятый ответ работает на платформах Unixy (когда доступен модуль readline), но если кто-то знает, как сделать эту работу под Windows, это будет очень полезно!

4b9b3361

Ответ 1

Возможно, что-то подобное сделает трюк:

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

Я не думаю, что stdin является потокобезопасным, поэтому вы можете потерять символы прерывистой нити (которую пользователь должен будет перепечатать в конце interrupt). Я преувеличил количество interrupt времени при вызове time.sleep. Вызов readline.get_line_buffer не отображает символы, которые теряются, поэтому все получается хорошо.

Обратите внимание, что сам stdout не является потокобезопасным, поэтому, если у вас есть несколько прерывистых потоков выполнения, это все равно может выглядеть грубым.

Ответ 2

Почему вы пишете свой собственный REPL с помощью raw_input()? Вы посмотрели класс cmd.Cmd? Изменить: Я просто нашел библиотеку sclapp, которая также может быть полезна.

Примечание: класс cmd.Cmd (и sclapp) может или не может напрямую поддерживать вашу исходную цель; вам может потребоваться подкласс и изменить его по мере необходимости, чтобы обеспечить эту функцию.

Ответ 3

запустите это:

python -m twisted.conch.stdio

Вы получите красивый, цветной, async REPL, без использования потоков. Когда вы вводите приглашение, цикл событий запускается.

Ответ 4

просмотрите модуль кода, он также позволяет создавать объекты для интерпретации кода python (бесстыдный плагин) https://github.com/iridium172/PyTerm позволяет создавать интерактивную команду линейные программы, которые обрабатывают исходный ввод с клавиатуры (например, ^ C поднимет KeyboardInterrupt).

Ответ 5

Это не ответ, но я бы посмотрел IPython, чтобы узнать, как они это делают.

Ответ 6

Я думаю, у вас есть 2 основных варианта:

  • Синхронизируйте свой вывод (т.е. блокируйте, пока он не вернется)
  • Отделите свой вход и ваш (асинхронный) вывод, возможно, в двух отдельных столбцах.