2013-05-02 24 views
1

我試圖使用Python和pywinusb-0.3.2從有效請求點擊Web服務器(requested_serial_number來自查詢字符串)時從USB稱重秤讀取數據。從處理函數中檢索數據/異常

所以我必須在我的do_GET下面的代碼:

all_hids = hid.find_all_hid_devices() 

if all_hids: 
    for index, device in enumerate(all_hids): 
     if device.serial_number == requested_serial_number: 
      device.open() 
      try: 
       device.set_raw_data_handler(scales_handler) 
       while True: 
        sleep(0.1) 
      except GotStableWeightException as e: 
       self.do_HEAD(200) 
       self.send_body(e.value) 

這是我scales_handler(加上自定義異常定義):

def scales_handler(data): 
    print("Byte 0: {0}".format(data[0])) 
    print("Byte 1: {0}".format(data[1])) 
    print("Byte 2: {0}".format(data[2])) 
    print("Byte 3: {0}".format(data[3])) 
    print("Byte 4: {0}".format(data[4])) 
    print("Byte 5: {0}".format(data[5])) 
    print("All: {0}".format(data)) 
    if data[1] == 4: 
     raise GotStableWeightException(data[4] + (256 * data[5])) 

class GotStableWeightException(Exception): 
    def __init__(self, value): 
     self.value = value 
    def __str__(self): 
     return repr(self.value) 

所以這個過程是:

  1. Python開始使用http.server的HTTPServer和監聽端口8000上的請求
  2. 請求進來並被髮送到我的do_GET函數。
  3. do_GET執行一些基本驗證,然後搜索匹配的USB HID(我的第一個代碼示例)。
  4. 如果找到匹配項,它將打開設備並傳入數據處理程序。

我想要實現:

我想允許數據處理程序,以保持從刻度讀數直到data[1] == 4(這表示從規模穩定的讀數)。此時,我想在我的do_GET中檢索此讀數並將其發送到等待的HTTP客戶端,關閉設備並結束該功能。

但是,我的GotStableWeightException沒有被抓到我的do_GET裏面,我想是因爲它被拋出了不同的線程。我是新來的編程多線程,並且遇到問題的時候遇到問題,一旦它符合data[1] == 4條件,我將如何獲得結果返回到do_GET

編輯

我能得到什麼:

這裏的輸出我在終端看到scales_handler

Byte 0: 3 
Byte 1: 4 
Byte 2: 2 
Byte 3: 0 
Byte 4: 204 
Byte 5: 0 
All: [3, 4, 2, 0, 204, 0] 
Exception in thread Thread-1: 
Traceback (most recent call last): 
    File "C:\Python33\lib\threading.py", line 639, in _bootstrap_inner 
    self.run() 
    File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\core.py", line 886, in run 
    hid_object._process_raw_report(raw_report) 
    File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\helpers.py", line 64, in new_function 
    return function_target(*args, **kw) 
    File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\core.py", line 714, in _process_raw_report 
    self.__raw_handler(helpers.ReadOnlyList(raw_report)) 
    File "C:\USB HID Scales\server.py", line 28, in scales_handler 
    raise GotStableWeightException(data[4] + (256 * data[5])) 
GotStableWeightException: 204 
+0

看不出有什麼明顯的錯誤,你確定你確實會引發異常嗎? 'scales_handler'中的打印語句產生了什麼? – danodonovan 2013-05-02 10:08:55

+0

我已經將輸出添加到原始問題中了......所以是的,非常確定:) – Alex 2013-05-02 10:31:44

+0

我不是專家,所以不是爲您提供全功能的解決方案,而是僅僅詢問一些其他問題。我希望這些問題可以幫助你解決你的情況。第一點是...爲什麼你使用異常將數據從程序的一個點傳遞到另一個點?雖然這可能奏效,但對我來說這聽起來不太好。異常是指錯誤捕獲和恢復,而不是發送信息。在使用線程時,我使用了消息隊列。我定義了一個包含發送/接收數據blob的隊列。這個隊列可以確保數據訪問的可靠性reliabl – victor 2013-05-02 10:09:18

回答

1

所以device是螺紋HidDevice類。正如你指出的那樣,在這個線程對象中引發一個異常不會被處理程序捕獲(你的do_GET)。但是,我想知道是否引發異常真的是最容易做的事情(異常往往被保留用於錯誤和問題)。爲了實現你的目標,是否可以使用一個global變量並做這樣的事情;

global e_value 
e_value = None 

def scales_handler(data): 
    print("Byte 0: {0}".format(data[0])) 
    print("Byte 1: {0}".format(data[1])) 
    print("Byte 2: {0}".format(data[2])) 
    print("Byte 3: {0}".format(data[3])) 
    print("Byte 4: {0}".format(data[4])) 
    print("Byte 5: {0}".format(data[5])) 
    print("All: {0}".format(data)) 
    if data[1] == 4: 
     e_value = data[4] + (256 * data[5])) 

devices = [] 
try: 
    for index, device in enumerate(all_hids): 
     if device.serial_number == requested_serial_number: 
      devices.append(device) 
      device.open() 
      device.set_raw_data_handler(sample_handler) 
    while True: 
     time.sleep(0.1) 
finally: 
    for device in devices: 
     device.close() 

if e_value is not None: 
    self.do_HEAD(200) 
    self.send_body(e_value) 

我無法證實你的設備是什麼,所以我要提醒,這是不是線程安全的 - 如果一個以上的設備具有data[1] == 4您只能通過e_value最後一臺設備來訪問它設置。 (雖然解決這個問題對於全局數組和對象來說很簡單)。

+0

感謝您的支持 - 它使我走上了正確的軌道。儘管我採用了稍微不同的方法,因爲我確實需要處理多個線程。我通過創建'ScalesDeviceHandler'對象解決了這個問題,該對象具有'scales_handler'方法,該方法在接收數據時設置成員屬性'weight'。當我打算從秤讀取時,我實例化對象,並將'scales_handler'方法傳遞給'set_raw_data_handler',然後輪詢對象自身的weight屬性,以查看它是否已由內部'scales_handler'方法設置。 – Alex 2013-05-02 14:54:36