Pexpect的spawn.expect()在检测进程输出方面似乎不可靠
我有一个类,叫做 ServerManager
,它用来监控和与另一个进程进行交互,使用的是 pexpect
这个工具。可惜的是,这种方式并不太干净,因为那个进程没有提供API接口。
这个 ServerManager
需要监控进程的输出,并在识别到特定模式时触发事件。因为需要监控的模式有很多,而 pexpect
的 spawn.expect()
会阻塞当前线程,所以这些“监听器”被放到不同的线程中,当它们匹配到自己的模式时,就会和主线程进行互动。
举个例子,就是等待用户连接或断开连接:
import pexpect
from threading import Thread,Lock
usersLock = Lock()
class ListenerThread(Thread):
def __init__(self, target, name=None, args=[], kwargs={}):
super(ListenerThread, self).__init__(name=name)
self.target = lambda: target(*args, **kwargs)
self.isStopped = False # add a way to safely halt this thread
def stop(self):
self.isStopped = True
def run(self):
while not self.isStopped: # run until told otherwise
try:
self.target()
except pexpect.TIMEOUT:
# we can't wait forever...
continue
except pexpect.EOF:
self.isStopped = True
class ServerManager(object):
def __init__(self):
self.process = pexpect.spawn(...) # Spawn the process
self.numberOfUsers = 0
# start up the listeners
self.listeners = []
connectListener = ListenerThread(self.waitForConnect, name="Connect listener")
connectListener.start()
disconnectListener = ListenerThread(self.waitForDisconnect, name="Disconnect listener")
disconnectListener.start()
self.listeners += [connectListener,disconnectListener] # keep track of the threads
def waitForConnect(self):
self.process.expect(...) # watch for the line that is printed when a user connects
usersLock.acquire()
try:
self.numberOfUsers += 1
finally:
usersLock.release()
def waitForDisconnect(self):
self.serverProcess.expect(...) # watch for the line that is printed when a user disconnects
usersLock.acquire()
try:
self.numberOfUsers -= 1
finally:
usersLock.release()
问题是,“连接”和“断开连接”的事件触发得非常不可靠。我创建了一个 ServerManager
的实例,并进行了10次连接和断开(每次操作之间大约等了10秒),在每次连接或断开后检查 numberOfUsers
。结果发现,最多也就更新了大约1/8的时间,经过多次尝试都是这样。
这是不是和 pexpect
的线程安全性有关?有没有更好的方法来监控这些事件,考虑到我唯一的与进程交互的方式就是监控它的命令行输出?
1 个回答
1
这里有两个线程在同一个文件描述符上进行阻塞调用。我会把这个实现成一个单线程的异步事件循环。expect
方法应该能够监视多个字符串,并为每个结果调用一个回调函数。我不太确定 pexpect 是否真的能做到这一点(我不使用它),但你可以仔细看看它的文档。