Показать графический интерфейс curses для скрипта, даже с перенаправленным выводом

Я хочу написать что-то вроде терминальной версии dmenu, которую можно использовать для поиска файла, а затем передать местоположение файла другой программе в конвейере, например:

my_script | xargs vim # search for a file and open in vim

Я пытался сделать это на питоне с перенаправлением вывода, но, похоже, это не работает с проклятиями.

import sys
import curses

prev_out = sys.stdout
print("1:", sys.stdout)
sys.stdout = open("/dev/tty", "w")
print("2:", sys.stdout)

window = curses.initscr()
window.addstr(1, 1, "testing")
window.getch()
curses.endwin()

sys.stdout = prev_out
print("3:", sys.stdout)

Когда я называю это так:

myscript > /dev/pts/1 # redirect output to another tty

print ведет себя так, как я ожидал (2 в исходном tty, 1 и 3 в другом), но пользовательский интерфейс curses отображается в /dev/pts/1.
Итак, мой вопрос: есть ли способ перенаправить вывод curses обратно в /dev/tty или есть другой способ отобразить текстовый графический интерфейс, который можно перенаправить, изменив sys.stdout?


person Vesok    schedule 14.05.2020    source источник


Ответы (1)


Я добился такого поведения, написав короткую оболочку bash для своего скрипта Python.

#!/bin/bash
# bash wrapper, that handles forking output between
# GUI and the output meant to go further down the pipe

# a pipe is created to catch the the wanted output
# date and username added in case of two scripts running at
# approximately the same time
fifo=/tmp/search_gui_pipe-$(whoami)-$(date +%H-%M-%S-%N)
[ ! -p "$fifo" ] && mkfifo $fifo

# python script is called in background, with stdin/out
# redirected to current tty, and location of the pipe file
# passed as an argument (also pass all args for parsing)
./search_gui.py "$fifo" $@ >/dev/tty </dev/tty &

# write the program output to stdout and remove the pipe file
cat "$fifo" && rm "$fifo"
person Vesok    schedule 03.06.2020