在检测进程输出时,Pexpect spawn.expect()似乎不可靠

时间:2011-08-21 03:10:10

标签: python multithreading thread-safety pexpect

我有一个类ServerManager,它使用pexpect监视另一个进程并与之交互。不幸的是,没有更简洁的方法来做到这一点。有问题的流程不提供API。

ServerManager需要监视进程的输出并在识别特定模式时触发事件。因为要监视多个这样的模式,并且pexpect的{​​{1}}阻塞当前线程,所以这些“侦听器”被分离成单独的线程,当它们在模式上匹配时与主线程交互。

一个这样的例子是等待用户连接/断开连接:

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() 的实例并连接/断开了10次(每次操作之间等待大约10秒),在每次连接/断开连接后检查ServerManager。在多次试验中,它仅在最多1/8的时间内更新。

这是numberOfUsers中线程安全的问题吗?考虑到我与流程接口的唯一方法是监控其命令行输出,是否有更好的方法来监视这些类型的事件?

1 个答案:

答案 0 :(得分:1)

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