3

My screen displays <type 'exceptions.TypeError'>: 'NoneType' object is not callable when I run this code below:

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)

This is error details:

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

What's wrong with my code? Thanks a lot.

changzhi
  • 2,641
  • 9
  • 36
  • 46
  • Using `super(ThreadUrl, self).__init__()` other than `threading.Thread.__init__(self)` is recommended, see http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods – shuiyu Mar 06 '14 at 06:50
  • Thanks your comment. But it occurs the same error. – changzhi Mar 06 '14 at 06:53
  • on my system (win 7 x64; python 2.7.1 32bit your code works fine – Mr. Girgitt Mar 06 '14 at 07:53
  • Also works fine on mine (OS X 10.9.1, python 2.7.5 64bit). Btw, I wonder whether `for host in hosts: queue.put(host)` should be OUT of , and BEFORE threads creation loop ? – shuiyu Mar 06 '14 at 08:46

1 Answers1

2

It's a python 2.7 bug - Shutdown exception in daemon thread. You could make the threads non-deamon and pass a sentinel through the queue to signal them to exit, then join them from the main thread.

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)
rectalogic
  • 1,266
  • 11
  • 12