2014-09-23 86 views
0

我寫了一個程序,它使用線程在主程序循環時保持連接處於活動狀態,直到它出現異常或手動關閉。我的程序以1小時的間隔運行,連接的超時時間爲20分鐘,因此爲我的架構中存在的每個連接元素生成一個線程。因此,如果我們有兩臺連接到它的服務器連接到這兩臺服務器並保持連接,並通過每臺服務器循環檢索數據。什麼是殺死異常循環python線程的最佳方法?

我寫的程序工作正常,但我似乎無法找到一種方法來處理它自己引發異常的程序。這就是說,當主程序除外時,我無法找到處理線程的適當方式。當程序除了它之外,它會掛起,因爲線程不是很好,它不會正確關閉,並且必須手動關閉。

有關如何處理程序退出時清理線程的任何建議?

這是我的線程:

def keep_vc_alive(vcenter,credentials, api): 
    vm_url = str(vcenter._proxy.binding.url).split('/')[2] 
    while True: 
     try: 
     logging.info('staying connected %s' % str(vm_url)) 
     vcenter.keep_session_alive() 
     except: 
     logging.info('unable to call current time of vcenter %s attempting to reconnect.' % str(vm_url)) 
     try: 
      vcenter = None 
      connected,api_version,uuid,vcenter = vcenter_open(60, api, * credentials) 
     except: 
      logging.critical('unable to call current time of vcenter %s killing application, please have administrator restart the module.' % str(vm_url)) 
      break 
     time.sleep(60*10) 

然後我異常清理代碼如下,很明顯,我know.stop()不工作,但我真的不知道該怎麼辦是什麼即時嘗試做。

except Abort: # Exit without clearing the semaphore 
    logging.exception('ApplicationError') 
    try: 
     config_values_vc = metering_config('VSphere',['vcenter-ip','username','password','api-version'])  
     for k in xrange(0, len(config_values_vc['username'])): # Loop through each vcenter server 
     vc_thread[config_values_vc['vcenter-ip'][k]].stop() 
    except: 
     pass 
    #disconnect vcenter 
    try: 
     for vcenter in list_of_vc_connections: 
     list_of_vc_connections[vcenter].disconnect() 
    except: 
     pass 
    try:  # Close the db is it is open (db is defined) 
     db.close() 
    except: 
     pass 
    sys.exit(1) 

except SystemExit: 
    raise 

except: 
    logging.exception('ApplicationError') 
    semaphore('ComputeLoader', False) 
    logging.critical('Unexpected error: %s' % sys.exc_info()[0]) 
    raise 
+1

這對你可能是有用的:http://stackoverflow.com/questions/32 3972/is-there-any-way-to-kill-a-thread-in-python – user3885927 2014-09-23 16:13:12

+0

'雖然True'從來都不是一個好主意,即使在一個線程中也是如此... – georg 2014-09-23 16:22:09

回答

1

在Python中停止線程的公認方法是使用threading.Event對象。

算法遵循通常是類似以下內容:

import threading 
... 
threads = [] 
#in the main program 
stop_event = threading.Event() 
#create thread and store thread and stop_event together 
thread = threading.Thread(target=keep_vc_alive, args=(stop_event)) 
threads.append((thread, stop_event)) 
#execute thread 
thread.start() 
... 
#in thread (i.e. keep_vc_alive) 
# check is_set in stop_event 
while not stop_event.is_set(): 
    #receive data from server, etc 
    ... 
... 
#in exception handler 
except Abort: 
    #set the stop_events 
    for thread, stop_event in threads: 
     stop_event.set() 
    #wait for threads to stop 
    while 1: 
     #check for any alive threads 
     all_finished = True 
     for thread in threads: 
      if thread.is_alive(): 
       all_finished = False 
     #keep cpu down 
     time.sleep(1) 
+0

非常感謝,真棒,我不能在任何地方都找不到,謝謝。 – 2014-09-23 17:53:02

2

而是睡覺,等待一個threading.Event()

def keep_vc_alive(vcenter,credentials, api, event): # event is a threading.Event() 
    vm_url = str(vcenter._proxy.binding.url).split('/')[2] 
    while not event.is_set(): # If the event got set, we exit the thread 
     try: 
     logging.info('staying connected %s' % str(vm_url)) 
     vcenter.keep_session_alive() 
     except: 
     logging.info('unable to call current time of vcenter %s attempting to reconnect.' % str(vm_url)) 
     try: 
      vcenter = None 
      connected,api_version,uuid,vcenter = vcenter_open(60, api, * credentials) 
     except: 
      logging.critical('unable to call current time of vcenter %s killing application, please have administrator restart the module.' % str(vm_url)) 
      break 
     event.wait(timeout=60*10) # Wait until the timeout expires, or the event is set. 

然後,在你的主線程,在異常設置的事件處理代碼:

except Abort: # Exit without clearing the semaphore 
    logging.exception('ApplicationError') 
    event.set() # keep_alive thread will wake up, see that the event is set, and exit 
相關問題