我有一個類ServerManager
,它監視並使用pexpect
與另一個進程進行交互。不幸的是,沒有更簡單的方法來做到這一點。相關流程不提供API。Pexpect spawn.expect()在檢測過程輸出中似乎不可靠
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'接受匹配模式列表而不是單個模式的能力。 –
@SpencerSmall你應該'接受'這個答案,這是正確的,這是'pexpect'是如何設計的。 – Anentropic