簡體   English   中英

在從 Python 管道中不斷讀取 stdin 的同時獲取用戶輸入?

[英]Get user input while continually reading stdin from a pipe in Python?

給定一個名為interactive的程序,它以這樣的方式啟動:

% tail -f logfile | interactive

在Python中,我們可以重新設置stdin比其他一些stdin通過覆蓋參考:

import sys 

text = sys.stdin.read() 

# rebind sys.stdin to tty 
sys.stdin = open("/dev/tty") 
user_in = input("Selection? : ") 

但是,如果我們需要永遠繼續從我們通過管道輸入的文件中讀取,這將不起作用,因為原始stdin管道沒有被釋放。 有沒有辦法從我們正在管道中獲取輸入並將其移動到單獨的管道中,以便我們仍然可以使用stdin來獲取用戶輸入?

就它們作為文件流的狀態而言, stdin/stdout/stderr 1沒有什么特別之處。 程序啟動后,您可以像對待任何常規文件描述符一樣對待它們。 所以重新綁定stdin的想法是沒有必要的。 相反,這似乎更像是一個關於如何設置並發輸入流的問題。

我的第一個傾向是使用幾個線程,但我確信這可以使用async/await和其他一些方法來完成。 在這種情況下,線程應該沒問題,因為兩個線程最終都會受到 IO 限制並且應該釋放 GIL(每個人都喜歡對 GIL 感到興奮)。 這非常接近(不完美,但在球場內......):

#!/usr/bin/env python3

import sys
import threading
from time import sleep

user_input = ""

def tty_reader():
    global user_input
    read_fd = open("/dev/tty", 'r')
    while 1:
        print("interactive-% ", end="", flush=True)
        user_input = read_fd.readline() # block for input
        print("\nUser Input: " + str(user_input), end="", flush=True)

def pipe_reader():
    while 1:
        stdin_text = sys.stdin.readline() # block for input
        if stdin_text != user_input:
            print("\nPipe Message: " + str(stdin_text), end="", flush=True)

t_tty_reader = threading.Thread(target=tty_reader)
t_pipe_reader = threading.Thread(target=pipe_reader)
t_pipe_reader.start()
sleep(3) # to let the existing 'tail' lines finish printing
t_tty_reader.start()

將它保存到一個文件中, chmod 755它,然后像這樣運行:

tail -f <some file> | ./<python script>

這將啟動 2 個線程。 一個從/dev/tty讀取,另一個從應該附加到tail -f命令的stdout的原始stdin讀取。 兩個線程大部分時間都花在阻塞輸入上。 正如我所說,這可能會更好,但它顯示了總體思路。


1:它們仍然很特別,原因有幾個:你免費得到它們; 它們以一定的標准化配置預先管道; 它們在/dev作為設備得到了一些特殊待遇; 子進程繼承它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM