У меня есть класс 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
?Есть ли лучший способ следить за такого рода событиями, учитывая, что мой единственный способ взаимодействия с процессом - это мониторинг его вывода из командной строки?