Чтобы использовать программу командной строки с интерактивным TTY, вам просто нужно выполнить эту программу в оболочке (конечно, программа должна выполнять блокирующие операции ввода-вывода на STDIN / STDOUT). Например: python -i.
Но вы также можете сделать это: cat - | python -i. Это полезно для подачи в STDIN сначала файла, а затем интерактивного телетайпа. Например: cat prelude.py - | python -i. Таким образом, вы получите интерактивный TTY после, передающий все содержимое скрипта в STDIN. Я знаю, что есть и другие способы загрузить скрипт в интерактивную оболочку Python, это всего лишь пример.
Я хочу написать сценарий Python, который ведет себя таким же образом. Вот мой текущий сценарий тестирования:
import os
import sys
import threading
def main():
thread_loop = True
def thread_func():
unbuf_fd = os.fdopen(sys.stdin.fileno(), 'rb', 0)
sys.stdin.close()
sys.stdin = unbuf_fd
unbuf_fd = os.fdopen(sys.stdout.fileno(), 'wb', 0)
sys.stdout.close()
sys.stdout = unbuf_fd
while(thread_loop):
sys.stdout.write(sys.stdin.read(1))
sys.stdout.write(b'Exiting...\n')
def signal_func(sig, frame):
global thread_loop
print('You pressed Ctrl+C.')
thread_loop = False
forward_std = threading.Thread(target=thread_func, args=())
forward_std.start()
forward_std.join()
if __name__ == '__main__':
main()
И python test.py, и cat - | python test.py работают, но, в отличие от python -i, у меня есть отголоски того, что залито в STDIN.
Как я могу отключить это эхо? Следующий код работает с python test.py:
fd = sys.stdin.fileno()
fd_attr = tty.tcgetattr(fd)
tty.setcbreak(fd)
Но с cat - | python test.py я получаю следующую ошибку:
Traceback (most recent call last):
File "tata.py", line 33, in <module>
main()
File "tata.py", line 25, in main
fd_attr = tty.tcgetattr(fd)
termios.error: (25, 'Inappropriate ioctl for device')
Есть ли общий способ отключить эхо для STDIN, подключено ли оно к каналу или нет? Есть ли конкретный способ отключить эхо для передаваемого по каналу STDIN и который я могу использовать, когда sys.stdin.isatty() вернет False?
Спасибо за ваш совет !
Обратите внимание, что cat foo.py - | python -i выводит нет содержимое foo.py, но выводит эхо ввода с клавиатуры. Вам не нужно делать ничего особенного, чтобы добиться такого поведения.
"Почему вы вообще хотите это сделать?" Ну, я хотел контролировать, какой символ из STDIN будет печататься в STDOUT, но я неправильно понимал связь между STDIN и TTY. Спасибо за вашу помощь.






В случае
cat - | python test.pyсценарий Python не имеет дескриптора для TTY (только для канала отcat), поэтому будет сложно что-либо сделать с любым эхом клавиатуры. Единственный подход, который я могу придумать, - это рекурсивно пройти вверх по дереву процессов к каждому родительскому элементу, выяснить, является ли его стандартный ввод TTY от/proc/PID/fd/0, и, если да, открыть его и выполнить соответствующий ioctl. Но это уродливый хакер, который во многих ситуациях может пойти не так, как надо. Почему вы вообще хотите это сделать?