ServerManager
を使用して別のプロセスを監視およびインターフェースするクラス、がありますpexpect
。残念ながら、これを行うためのよりクリーンな方法はありません。問題のプロセスはAPIを提供していません。
プロセスのServerManager
出力を監視し、特定のパターンを認識したときにイベントをトリガーする必要があります。監視するそのようなパターンは複数あり、は現在pexpect
のspawn.expect()
スレッドをブロックするため、これらの「リスナー」は、パターンが一致するとメインスレッドと相互作用する個別のスレッドにスピンオフされます。
そのような例の1つは、ユーザーが接続/切断するのを待っています。
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
ですか?プロセスとのインターフェースの唯一の手段がコマンドライン出力を監視することであるとすると、これらの種類のイベントを監視するためのより良い方法はありますか?