Pexpect的spawn.expect()在检测进程输出方面似乎不可靠

0 投票
1 回答
1953 浏览
提问于 2025-04-17 00:01

我有一个类,叫做 ServerManager,它用来监控和与另一个进程进行交互,使用的是 pexpect 这个工具。可惜的是,这种方式并不太干净,因为那个进程没有提供API接口。

这个 ServerManager 需要监控进程的输出,并在识别到特定模式时触发事件。因为需要监控的模式有很多,而 pexpectspawn.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 是否真的能做到这一点(我不使用它),但你可以仔细看看它的文档。

撰写回答