Понимание Threading в python: как сказать `run ()` возвращать обработанные данные? - PullRequest
0 голосов
/ 05 января 2012

Я прочитал о потоках в источниках разработки IBM и нашел следующий пример.

В общем, я понимаю, что здесь происходит, за исключением одной важной вещи. Кажется, что работа выполняется в функции run(). В этом примере run() только печатает строку и сигнализирует очереди, что задание выполнено.

Что если бы мне пришлось вернуть некоторые обработанные данные? Я думал о том, чтобы кэшировать его в глобальной переменной и получить к нему доступ позже, но, похоже, это неправильный путь.

Любой совет?

Возможно, мне следует уточнить: Моя интуиция подсказывает мне добавить return processed_data к run() сразу после self.queue.task_done(), но я не могу понять, где отловить это возвращение, поскольку это не так. Для меня очевидно, где run() называется.

#!/usr/bin/env python
import Queue
import threading
import urllib2
import time

hosts = ["http://yahoo.com", "http://google.com", "http://amazon.com",
"http://ibm.com", "http://apple.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 bytes of page
            url = urllib2.urlopen(host)
            print url.read(1024)

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

start = time.time()
def main():

    #spawn a pool of threads, and pass them queue instance 
    for i in range(5):
        t = ThreadUrl(queue)
        t.setDaemon(True)
        t.start()

    #populate queue with data   
    for host in hosts:
        queue.put(host)

    #wait on the queue until everything has been processed     
    queue.join()

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

Ответы [ 2 ]

3 голосов
/ 05 января 2012

Вы не можете вернуть значение из run, и в любом случае обычно есть более одного элемента для обработки в каждом потоке, поэтому вы не хотите возвращать вообще после обработки одного значения (см. while петли в каждом потоке).

Я бы использовал другую очередь для возврата результатов:

queue = Queue.Queue()
out_queue = Queue.Queue()

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

            #grabs urls of hosts and saves first 1024 bytes of page
            url = urllib2.urlopen(host)
            out_queue.put(url.read(1024))

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

...

def main():
    ...
    #populate queue with data   
    for host in hosts:
        queue.put(host)

    #don't have to wait until everything has been processed if we don't want to

    for _ in range(len(hosts)):
        first_1k = out_queue.get()
        print first_1k

или сохранить результат в той же очереди:

class WorkItem(object):
    def __init__(self, host):
        self.host = host

class ThreadUrl(threading.Thread):
    ...
    def run(self):
        while True:
            #grabs host from queue
            work_item = self.queue.get()
            host = work_item.host

            #grabs urls of hosts and saves first 1024 bytes of page
            url = urllib2.urlopen(host)
            work_item.first_1k = url.read(1024)

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

...

def main():
    ...
    #populate queue with data   
    work_items = [WorkItem(host) for host in hosts]
    for item in work_items:
        queue.put(item)

    #wait on the queue until everything has been processed     
    queue.join()

    for item in work_items:
        print item.first_1k
0 голосов
/ 13 ноября 2013

проблема с использованием метода очереди заключается в следующем: порядок, в котором могут выполняться потоки, является случайным.Следовательно, элемент очереди может не обязательно отражать результат этой конкретной позиции.В этом примере, если google.com выполняется до yahoo.com, то в очереди есть данные google до yahoo, поэтому при ее получении результаты неверны.

...