Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pexpect spawn.expect()在检测进程输出时似乎不可靠_Python_Multithreading_Thread Safety_Pexpect - Fatal编程技术网

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

Python Pexpect spawn.expect()在检测进程输出时似乎不可靠,python,multithreading,thread-safety,pexpect,Python,Multithreading,Thread Safety,Pexpect,我有一个类,ServerManager,它使用pexpect监视另一个进程并与之交互。不幸的是,没有一种更干净的方法来做到这一点。该过程没有提供API ServerManager需要监控流程的输出,并在识别特定模式时触发事件。因为要监视多个这样的模式,并且pexpect的spawn.expect()会阻止当前线程,所以这些“侦听器”会分离为单独的线程,当它们与模式匹配时,这些线程会与主线程交互 其中一个示例是等待用户连接/断开连接: import pexpect from threading i

我有一个类,
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
中的线程安全问题吗?考虑到我与进程交互的唯一方法是监视其命令行输出,有没有更好的方法来监视这类事件?

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

谢谢!我忽略了
expect
接受要匹配的模式列表而不是单一模式的能力。@Spencesmall您应该“接受”这个答案,这是正确的
peexpect
就是这样设计的。