具有多个线程的Python脚本仅在调试模式下正常工作

时间:2016-03-06 18:23:12

标签: python json multithreading

我目前正在使用一个带有多个线程的Python 2.7脚本。其中一个线程在长轮询模式下侦听JSON数据,并在接收或在一段时间后进入超时后解析它。我注意到它只在调试模式下工作(我使用Wing IDE)。在正常运行的情况下,在进入" for"之前,看起来这个脚本的特定线程在第一次GET请求之后挂起。环。循环条件不会影响结果。与此同时,其他线程继续正常工作。

我认为这与多线程有关。如何正确排除故障并解决此问题?

下面我把类的代码负责长轮询工作。

class Listener(threading.Thread):

def __init__(self, router, *args, **kwargs):
    self.stop = False

    self._cid = kwargs.pop("cid", None)
    self._auth = kwargs.pop("auth", None)
    self._router = router
    self._c = webclient.AAHWebClient()

    threading.Thread.__init__(self, *args, **kwargs)

def run(self):
    while True:
        try:
            # Data items that should be routed to the device is retrieved by doing a 
            # long polling GET request on the "/tunnel" resource. This will block until
            # there are data items available, or the request times out
            log.info("LISTENER: Waiting for data...")

            response = self._c.send_request("GET", self._cid, auth=self._auth)

            # A timed out request will not contain any data             
            if len(response) == 0:
                log.info("LISTENER: No data this time")             
            else:
                items = response["resources"]["tunnel"]
                undeliverable = []

                #print items # - reaching this point, able to return output

                for item in items:

                    # The data items contains the data as a base64 encoded string and the 
                    # external reference ID for the device that should receive it
                    extId = item["extId"]
                    data = base64.b64decode(item["data"])

                    # Try to deliver the data to the device identified by "extId"
                    if not self._router.route(extId, data):
                        item["message"] = "Could not be routed"
                        undeliverable.append(item)

                # Data items that for some reason could not be delivered to the device should
                # be POST:ed back to the "/tunnel" resource as "undeliverable"
                if len(undeliverable) > 0:
                    log.warning("LISTENER: Sending error report...")
                    response = self._c.send_request("POST", "/tunnel", body={"undeliverable": undeliverable}, auth=self._auth)

            except webclient.RequestError as e:
                log.error("LISTENER: ERROR %d - %s", e.status, e.response)

UPD:

class Router:
def route(self, extId, data):

    log.info("ROUTER: Received data for %s: %s", extId, repr(data))
    # nothing special
    return True

1 个答案:

答案 0 :(得分:0)

如果您正在使用CPython解释器you're not actually system threading

  

CPython实现细节:在CPython中,由于Global   解释器锁,只有一个线程可以一次执行Python代码   (即使某些面向性能的库可能会克服   这个限制)。如果您希望您的应用程序更好地使用   建议您使用多核机器的计算资源   使用多处理。但是,线程仍然是一个合适的模型   如果你想同时运行多个I / O绑定任务。

因此,在收听第一个请求时,您的进程可能会锁定,因为您需要长时间轮询。

多处理可能是更好的选择。我没有尝试过长时间轮询,但the Twisted framework也可能适用于您的情况。