многопоточная синхронизация python - PullRequest
0 голосов
/ 02 сентября 2011

У меня проблема с синхронизацией при работе с cPython. У меня два файла, я их разбираю и возвращаю нужный результат. Тем не менее, приведенный ниже код действует странно и возвращает три раза вместо двух, плюс не возвращается в том порядке, в котором я поставил их в очередь. Вот код:

import Queue
import threading
from HtmlDoc import Document

OUT_LIST = []

class Threader(threading.Thread):
    """
    Start threading
    """
    def __init__(self, queue, out_queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.out_queue = out_queue


    def run(self):
        while True:
            if self.queue.qsize() == 0: break

            path, host = self.queue.get()

            f = open(path, "r")
            source = f.read()
            f.close()

            self.out_queue.put((source, host))           
            self.queue.task_done()



class Processor(threading.Thread):
    """
    Process threading
    """
    def __init__(self, out_queue):
        self.out_queue = out_queue
        self.l_first = []
        self.f_append = self.l_first.append
        self.l_second = []
        self.s_append = self.l_second.append
        threading.Thread.__init__(self)


    def first(self, doc):
        # some code to to retrieve the text desired, this works 100% I tested it manually

    def second(self, doc):
        # some code to to retrieve the text desired, this works 100% I tested it manually

    def run(self):
        while True:
            if self.out_queue.qsize() == 0: break

            doc, host = self.out_queue.get()

            if host == "first":
                self.first(doc)
            elif host == "second":
                self.second(doc)

            OUT_LIST.extend(self.l_first + self.l_second)

            self.out_queue.task_done()


def main():

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

    queue.put(("...first.html", "first"))
    queue.put(("...second.html", "second"))

    qsize = queue.qsize()

    for i in range(qsize):
        t = Threader(queue, out_queue)
        t.setDaemon(True)
        t.start()

    for i in range(qsize):
        dt = Processor(out_queue)
        dt.setDaemon(True)
        dt.start()

    queue.join()
    out_queue.join()

    print '<br />'.join(OUT_LIST)

main()

Теперь, когда я печатаю, я хотел бы сначала напечатать содержимое «первого», а затем содержимое «второго». Может кто-нибудь мне помочь?

ПРИМЕЧАНИЕ. Я работаю с потоками, потому что на самом деле мне придется подключаться более чем к 10 местам одновременно и получать результаты. Я считаю, что многопоточность является наиболее подходящим способом решения такой задачи

Ответы [ 3 ]

2 голосов
/ 02 сентября 2011

Я работаю с потоками, потому что на самом деле мне придется соединять более 10 мест одновременно и получать результаты. Я считаю, что многопоточность является наиболее подходящим способом решения такой задачи

Многопоточность на самом деле является одним из наиболее подверженных ошибкам способов управления несколькими одновременными соединениями. Более мощный и более отлаживаемый подход заключается в использовании управляемой событиями асинхронной сети, например, реализованной Twisted . Если вы заинтересованы в использовании этой модели, вы можете проверить это введение .

1 голос
/ 02 сентября 2011

Я не разделяю того же мнения, что многопоточность - лучший способ сделать это (IMO, некоторые события / механизм выбора будет лучше), но проблема с вашим кодом может быть в переменных t и dt. У вас есть назначения в цикле, и экземпляры объектов должны храниться где угодно, поэтому возможно, что ваш новый экземпляр Thread / Processor будет удален в конце каждого цикла.

Было бы более понятно, если вы покажете нам точный вывод этого кода.

0 голосов
/ 02 сентября 2011

1) Вы не можете контролировать порядок завершения работы.Это зависит от времени выполнения, поэтому для возврата результатов по вашему желанию вы можете создать глобальный словарь с объектами задания, такими как job_results: {'first': None, 'second': None} и сохранить результаты здесь, чем вы можете получить данные по желаемомупорядок

2) self.first и self.second следует очищать после каждого обработанного документа, иначе у вас будут дубликаты в OUT_LIST

3) Вы можете использовать мультиобработку с модулем подпроцесса и поставитьнапример, все данные результатов в файлы CSV сортируют их по своему желанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...