0

我有一个类,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吗?鉴于我与进程交互的唯一方法是监视其命令行输出,是否有更好的方法来监视此类事件?

4

1 回答 1

1

这里有两个线程对同一个文件描述符进行阻塞调用。我将实现这是一个单线程异步事件循环。该expect方法应该能够监视一个以上的字符串可以为一次调用的每个结果调用一个回调函数。我不确定 pexpect 是否真的可以做到这一点(我不使用它),但请仔细查看它的文档。

于 2011-08-21T05:35:40.650 回答