Есть ли способ интерактивно программировать приложение Python curses? - PullRequest
13 голосов
/ 26 августа 2011

Есть ли способ создать второй терминал, чтобы все вызовы функций curses работали на этом, а не на существующем терминале? Я работаю намного быстрее, когда могу попробовать что-то в интерактивном режиме, поэтому я хотел бы иметь возможность запускать интерактивный интерпретатор python в одном терминале и видеть вывод curses в другом.

Как таковой, вызов initscr() в интерактивном окне либо дает сбой (PyDev), либо навсегда отменяет обновление окна с хоста (Spyder), либо вызывает странное поведение в консоли (IPython).

Можно ли захватить другой терминал, используя setupterm()? Если так, то где взять другую строку TERM для вызова?

Ответы [ 3 ]

3 голосов
/ 01 сентября 2011

Я не верю, так как модуль curses в основном (полностью?) Реализован на уровне C.Маловероятно, что он обеспечит такие хуки, хотя, если вы знакомы с языком, возможно, стоит поискать в источнике.

Однако, читая ваш вопрос, я подумал о другой технике, которую я использую в других контекстах.Вы можете сохранить скрипт через другой терминал / редактор и использовать технику, аналогичную команде dnotify (или даже простой опрос), чтобы загрузить его в работающую программу.

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

Вам придется создать некоторую инфраструктуру, но это, вероятно, будет гораздо проще, чем добавить поддержку нескольких устройств в curses.

3 голосов
/ 02 сентября 2011

Вы можете использовать code.InteractiveConsole и SocketServer, чтобы присоединить интерактивную оболочку python к сокету и выполнить свою разработку через это.Простой пример выглядит следующим образом:

import sys
import SocketServer
from code import InteractiveConsole

class InteractiveServer(SocketServer.BaseRequestHandler):
   def handle(self):
        file = self.request.makefile()
        shell = Shell(file)
        try:
           shell.interact()
        except SystemExit:
           pass


class Shell(InteractiveConsole):
    def __init__(self, file):
        self.file = sys.stdout = file
        InteractiveConsole.__init__(self)
        return

    def write(self, data):
       self.file.write(data)
       self.file.flush()

    def raw_input(self, prompt=""):
       self.write(prompt)
       return self.file.readline()

if __name__ == '__main__':
   HOST, PORT = "0.0.0.0", 9999

   server = SocketServer.TCPServer((HOST, PORT), InteractiveServer)
   server.serve_forever()

После того, как вы его запустите, вы можете подключиться к порту 9999 с другого терминала и делать свое дело.Это можно увидеть на этом скриншоте (PNG)

Основы использования InteractiveConsole взяты из этого поста .Я изменил его для работы с SocketServer для другого проекта, над которым я работал.

1 голос
/ 30 августа 2011

Ну, я не уверен, что полностью понимаю, что вы пытаетесь сделать.Но то, что я понял, это то, что вы хотите иметь стандартную консоль Python, где вы можете вводить свой код динамически.Но когда вы вызываете, например, функцию, результат обработки этой функции появится в другом терминале?

Ну ... для того, чтобы она работала, я думаю, что используемая архитектура будет "клиентской"-server».

Поскольку у процесса есть stdout и stderr, а в многопроцессорной архитектуре вы можете использовать stderr в качестве канала вывода функции.Но проблема заключается в инициализации другого терминала, который отделен от основного.(без перекрытия внутри одного и того же пространства).

Если ваша основная программа инициализирует сервер (в другом процессе Python из-за самой природы сервера), который отправляет выходные данные всем подключенным к нему клиентам.Таким образом, вы можете визуализировать вывод функции на нескольких терминальных клиентах и ​​/ или другом компьютере, способном подключиться к вашему серверу.

На мой взгляд, это гораздо проще, чем пытаться использовать пакет curses.Но если единственная цель состоит в том, чтобы получить представление о вашем коде, я думаю, что он слишком сложен (без добавленной стоимости).


У вас все еще есть возможность выгрузить выходные данные функции в текстовый файл (журнал.TXT)

...