Python线程模块错误:'NoneType'对象不可调用

时间:2014-03-06 06:40:09

标签: python multithreading

当我在下面运行此代码时,我的屏幕会显示<type 'exceptions.TypeError'>: 'NoneType' object is not callable

import threading
import urllib2
import Queue
import time

hosts = ["http://baidu.com", "http://yahoo.com"]

queue = Queue.Queue()

class ThreadUrl(threading.Thread):
    """ Threaded Url Grab """
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            #grabs host from queue
            host = self.queue.get()

            #grabs urls of hosts and prints first 1024 byte of page
            url = urllib2.urlopen(host)

            #signals to queue job is done
            self.queue.task_done()

start = time.time()
def main():
    for i in range(2):
        t = ThreadUrl(queue)
        t.setDaemon(True)
        t.start()

        for host in hosts:
            queue.put(host)

    queue.join()

main()
print "Elapsed Time: %s" % (time.time() - start)

这是错误详情:

Exception in thread Thread-3 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 808, in __bootstrap_inner
File "url_thread.py", line 21, in run
File "/usr/local/lib/python2.7/Queue.py", line 168, in get
File "/usr/local/lib/python2.7/threading.py", line 332, in wait
<type 'exceptions.TypeError'>: 'NoneType' object is not callable

我的代码出了什么问题?非常感谢。

1 个答案:

答案 0 :(得分:1)

这是一个python 2.7 bug - Shutdown exception in daemon thread。 你可以使线程非deamon并通过队列传递一个sentinel来通知它们退出,然后从主线程加入它们。

import threading
import urllib2
import Queue
import time

hosts = ["http://baidu.com", "http://yahoo.com"]

queue = Queue.Queue()

class ThreadUrl(threading.Thread):
    """ Threaded Url Grab """
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            #grabs host from queue
            host = self.queue.get()
            if host is None:
                self.queue.task_done()
                return

            #grabs urls of hosts and prints first 1024 byte of page
            url = urllib2.urlopen(host)

            #signals to queue job is done
            self.queue.task_done()

start = time.time()
def main():
    threads = [ThreadUrl(queue) for _ in range(2)]
    map(lambda t: t.start() threads)
    for i in range(2):
        for host in hosts:
            queue.put(host)
    for t in threads:
        queue.put(None)
    queue.join()
    map(lambda t: t.join() threads)

main()
print "Elapsed Time: %s" % (time.time() - start)