在python中,定義一個方法,直接呼叫可以,但是建立一個執行緒來呼叫就可能導致失敗。這種現像多出現在使用com物件進行系統操作時,而且是以執行緒的形式呼叫。
異常提示如下:
syntax error。WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex] (no underlying exception)
仔細觀察的話,異常提示中已經給出了解決方案。在執行一個執行緒的時候需要呼叫pythoncom.CoInitialize()方法。鄙人在程式中使用了WMI模組,試圖獲取部分系統資訊。
異常的原因(推測)是com的機制問題。 由於COM機制允許任意兩個組件之間相互通信而不必關心是在何種計算機上的何種操作系統下運行,也不用關心組件是使用何種語言編制的,這使COM技術擁有了強大的生命力。初始化COM環境的目的是讓呼叫COM的API運作正常,也就是在COM操作之前呼叫CoInitialize或CoInitializeEX所以在執行緒函數中,如果使用com物件就必須呼叫CoInitialize或CoInitializeEX ,同時在退出時使用CoUninitialize來釋放物件。
案例:
c === send = 0.0 t += float(t.BytesReceivedPersec) / 1024 / 1024+= float(t.BytesSentPersec) / 1024 / 1024 rec, send
這段程式碼是根據電腦的網路卡取得上下行的流量(即發送流量和接收流量),直接運行是可以的。但是在tornado的RequestHandler的get或post方法中使用時,會拋出異常syntax error及相關提示。在RequestHandler中,post或get請求被認為是一個後台的執行緒方法,所以需要在實例化WMI這個com元件之前先進行com實例化。
為什麼RequestHandler中post或get請求被認為是一個後台的執行緒方法?這個問題可以從使用tornado的程式碼中窺得一二。程式碼如下:
if __name__ == '__main__': app = tornado.web.Application( handlers=[(r"/test/(\w+)", testHandler), (r'/', MainHandler)] ) server = tornado.httpserver.HTTPServer(app) server = server.listen(8848) tornado.ioloop.IOLoop.instance().start();
在為tornado設定了路由規則之後,我們開啟了httpserver的服務,最後建立一個行程來讓tornado運作起來。而每次的post或get請求則是透過路由呼叫對應的Handler,這些都是在執行緒中執行的。故案例中透過com組件WMI來取得系統流量放在get方法中就會報錯。修改後如下:
def get(self): res = {} pythoncom.CoInitialize() c = wmi.WMI() interfaces = c.Win32_PerfRawData_Tcpip_NetworkInterface() print len(interfaces) rec = send = 0.0 for t in interfaces: print t.Name rec += float(t.BytesReceivedPersec) / 1024 / 1024 send += float(t.BytesSentPersec) / 1024 / 1024 print rec, send res["receive"] = "%.2f" % rec res["send"] = "%.2f" % send self._write_json(res)
模組中很有很多類型(類型也有很多屬性),在具體使用的過程中查詢起來很痛苦。案例中的統計流量用的是Win32_PerfRawData_Tcpip_NetworkInterface ,也有解決方案用的是Win32_PerfRawData_Tcpip_TCPv4 兩個統計到的資料差異很大,請根據實際情況來選擇。
以上是關於python方法無法在執行緒中使用的解決辦法的詳細內容。更多資訊請關注PHP中文網其他相關文章!