Процесс преобразования программы Python в многопоточное приложение? - PullRequest
1 голос
/ 28 февраля 2010

У меня есть кодовая база, которую я хочу разделить и добавить с помощью потоков, однако я относительно новичок в том, как с этим справиться. Пожалуйста, прежде чем читать дальше, уважайте мое желание НЕ просто переписывать этот код и возвращать его мне, когда проблема решена. Я бы предпочел решить проблему кем-то, кто направил меня в правильном направлении, а не тем, кто решил ее ЗА; Я плохо учусь таким образом.

Полностью функционирующая база кода здесь - для этого требуются библиотеки механизации и Beautifulsoup, которые можно установить с помощью easy_install.

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

Моя конечная цель состоит в том, чтобы упаковать это в поток, а затем делиться файлами cookie между другими инициализированными объектами браузера, чтобы делать другие вещи, пока мой исходный код работает "в фоновом режиме".

Я пробовал так:

class Recon(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        #Packed the stuff above my original while loop in here, minus functions.
    def run(self):
        #Packed my code past the while loop in here.
somevar = Recon()
somevar.start()

Проблема у меня заключается в том, что после запуска программы она будет запускать вещи в init , но потом она просто сидит и зависает на мне. Без трассировки, без ошибок, просто ничего не делает, даже не возвращает мою командную строку обратно в управление.

Могу ли я просто получить несколько советов или общее описание того, как это преобразовать? Я был ошеломлен и удалил код, который пытался использовать, поэтому у меня нет этого примера, но нужно ли мне добавлять «я»? ко всем моим переменным? Мне нужно просто определить мои переменные как глобальные?

Вот воспроизведение того, с чем у меня возникли проблемы после попытки конвертировать скрипт для использования threading .

1 Ответ

3 голосов
/ 28 февраля 2010

Пока у вас есть один поток (как в приведенном выше фрагменте, где вы создаете Recon только один раз), не должно иметь большого значения, что вы делаете, где; но, конечно, я думаю, что причина, по которой вы вводите многопоточность, заключается в том, чтобы в конечном итоге перейти к активным нескольким потокам.

Если это так, то первой ключевой проблемой является обеспечение того, чтобы у вас никогда не было двух или более потоков одновременно, пытающихся использовать одну и ту же общую систему / ресурс - например, несколько потоков записывают одновременно в ReconFile , в случае кода, указанного в URL-адресе пастбина.

Классический способ избежать таких проблем - использовать блокировку, но мой любимый способ совершенно иной: убедитесь, что к любому такому ресурсу обращаются только один выделенный поток, и используйте экземпляр Queue.Queue (по сути потокобезопасный), чтобы другие потоки отправляют рабочий запрос в выделенный поток (поэтому вместо прямой записи в ReconFile каждый поток будет составлять список строк, которые будут записаны непрерывно, а затем .put список в очереди, в которой находится рабочий поток "перезаписи файла") ожидание через .get).

Когда вам нужно получить результаты от таких действий (не здесь), запрашивающий поток помещает свою собственную «очередь, в которую нужно возвращать результаты» как часть «пакета рабочего запроса», который он передает работнику. очередь потока. Я представил гораздо больше подробностей об этой рекомендуемой архитектуре в главе о многопоточности «Python in a Nutshell», 2-е издание (и почему, как автор книги, я, конечно, никогда не рекомендую , если вы выполняете нелегальную загрузку из бесплатной пиратской копии моей книги, однако, я могу упомянуть, что есть множество сайтов, предлагающих такие пиратские копии для скачивания - легальный способ прочитать мою книгу бесплатно - это подписаться на пробное предложение для O'Reilly's " safari " веб-сайт онлайн-книг).

Это не решает конкретную проблему, которую вы наблюдаете, поскольку это происходит, когда у вас есть только один поток вокруг. Я заметил, что поток пытается выполнить много операций ввода-вывода для стандартного ввода и стандартного вывода, что, возможно, является проблематичным для потока - рассмотрите возможность ввода для потока до того, как вы его запустите (в основном для необходимого вывода используйте стандартный модуль Python logging, который равен гарантированно поточно-ориентирован. Вы все еще наблюдаете проблемы? Если это так, то следующим шагом будет добавление в ваш код вызовов logging.info, чтобы вы могли точно определить, где он остановился, - и рассказать нам об этом, чтобы мы могли попытаться помочь оттуда!

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