2011-08-21 107 views
0

我有一個類ServerManager,它監視並使用pexpect與另一個進程進行交互。不幸的是,沒有更簡單的方法來做到這一點。相關流程不提供API。Pexpect spawn.expect()在檢測過程輸出中似乎不可靠

ServerManager需要監視進程的輸出並在識別出特定模式時觸發事件。因爲有多個這樣的模式要監視,並且pexpectspawn.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?考慮到這類事件,有沒有更好的方法,因爲我唯一的方法就是通過監視命令行輸出來連接進程?

回答

1

您在這裏有兩個線程在同一個文件描述符上進行阻塞調用。我會實現這是一個單線程異步事件循環。方法expect應該能夠監視多個字符串可以調用來自一個調用的每個結果的回調函數。我不確定pexpect能夠實際做到這一點(我不使用它),但仔細看看它的文檔。

+0

謝謝!我忽略了'expect'接受匹配模式列表而不是單個模式的能力。 –

+0

@SpencerSmall你應該'接受'這個答案,這是正確的,這是'pexpect'是如何設計的。 – Anentropic