我正在编写一个python守护程序(使用python 3.7),该守护程序不断检查stdin上的数据是否可用(使用select
)并对其进行处理。数据可以包含非Unicode字符,因此守护程序需要从sys.stdin.buffer
而不是sys.stdin
读取。
该程序实际上有效。但是我正在使用第二个python脚本为该程序编写功能测试,该脚本以subprocess.Popen
启动守护程序,并将数据发送到stdin
并从其stdout
读取。由于某些原因,该部分不起作用。 proc.readline()
会永远阻塞,有些proc.stdin.write
永远不会到达子进程。
为简单起见,我有2个小脚本来说明问题。
目前,问题在于test.py中的第一个readline()
调用正在阻塞并且永不返回,而test2.py
已经向stdout写了整行。
# test.py
from subprocess import Popen, PIPE, TimeoutExpired
import time
import select
proc = Popen(["python", "test1.py"], stdin=PIPE, stdout=PIPE,
bufsize=0)
print("Writing")
proc.stdin.write("blablabla\n".encode('utf-8'))
time.sleep(2)
output = proc.stdout.readline()
print("Result")
print(output)
print("Writing")
proc.stdin.write("zxczxczxczxc\n".encode('utf-8'))
time.sleep(2)
output = proc.stdout.readline()
print("Result")
print(output)
proc.terminate()
print(proc.stdout.read())
#test1.py
import select
import signal
import sys
import logging
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
log = logging.getLogger()
STOP = False
def stop(frame, signal):
global STOP
STOP = False
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGINT, stop)
def input_available():
"""Check if data is available on stdin."""
data_available = select.select([sys.stdin], [], [], 0)
return sys.stdin in data_available[0]
data = ""
while not STOP:
if input_available():
char = sys.stdin.buffer.read(1)
try:
char = char.decode('utf-8')
data += char
except UnicodeDecodeError:
char = None
print("skipping char")
if char == '\n':
s = f"Got line {data}"
print(s)
log.debug(s)
data = ""
sys.stdout.flush()
编辑
从@ charles-duffy的赞誉中,我用strace运行了它。子程序中的程序似乎在read
调用上受阻?
这是strace输出的最后一位:
write(1, "Writing\n", 8Writing
) = 8
write(4, "blablabla\n", 10) = 10
select(0, NULL, NULL, NULL, {tv_sec=2, tv_usec=0}) = 0 (Timeout)
read(5,