Завершить длительные потоки Python - PullRequest
5 голосов
/ 04 августа 2009

Каков рекомендуемый способ завершения неожиданно долго работающих потоков в python? Я не могу использовать SIGALRM, так как

Необходимо соблюдать осторожность, если оба сигналы и потоки используются в та же программа. Фундаментальная вещь для помните при использовании сигналов и потоков одновременно есть: всегда выполнять signal () операции в основном потоке исполнения. Любой поток может выполнять будильник (), получает сигнал (), пауза (), setitimer () или getitimer (); только Основной поток может установить новый сигнал обработчик, и основной поток будет единственный, кто получает сигналы (это обеспечивается сигналом Python модуль, даже если основной поток реализация поддерживает отправку сигналы к отдельным потокам). это означает, что сигналы не могут быть использованы в качестве средства внутренней резьбы вместо этого используется блокировка.

Обновление: каждый поток в моем случае блокируется - это загрузка веб-страницы с помощью модуля urllib2, и иногда работа на слишком медленных сайтах занимает слишком много времени. Вот почему я хочу прекратить такие медленные темы

Ответы [ 4 ]

6 голосов
/ 04 августа 2009

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

Для конкретного случая OP (работа потоков заключается в загрузке веб-страниц, а некоторые потоки блокируются навсегда из-за неправильной работы сайтов), идеальным решением является витая - как обычно для сетевых задач , В других случаях многопроцессорная может быть лучше.

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

5 голосов
/ 27 ноября 2009

Как предположил Алекс Мартелли, вы можете использовать многопроцессорный модуль. Он очень похож на модуль Threading, поэтому вам легко начать работу. Ваш код может быть таким, например:

import multiprocessing

def get_page(*args, **kwargs):
    # your web page downloading code goes here

def start_get_page(timeout, *args, **kwargs):
    p = multiprocessing.Process(target=get_page, args=args, kwargs=kwargs)
    p.start()
    p.join(timeout)
    if p.is_alive():
        # stop the downloading 'thread'
        p.terminate()
        # and then do any post-error processing here

if __name__ == "__main__":
    start_get_page(timeout, *args, **kwargs)

Конечно, вам нужно каким-то образом получить возвращаемые значения кода загрузки вашей страницы. Для этого вы можете использовать multiprocessing.Pipe или multiprocessing.Queue (или другие способы, доступные при многопроцессорной обработке). Там есть больше информации, а также образцы, которые вы можете проверить на http://docs.python.org/library/multiprocessing.html.

Наконец, многопроцессорный модуль включен в Python 2.6. Он также доступен для Python 2.5 и 2.4 на pypi (вы можете использовать

многопроцессорная обработка easy_install

)

или просто посетите pypi, загрузите и установите пакеты вручную.

Примечание: я понимаю, что это было опубликовано некоторое время назад. У меня была похожая проблема с этим, и я наткнулся здесь и увидел предложение Алекса Мартелли. Если бы это было реализовано для моей проблемы и решил поделиться им. (Я хотел бы поблагодарить Алекса за то, что он указал мне правильное направление.)

1 голос
/ 04 августа 2009

Используйте объекты синхронизации и попросите завершить поток. В основном, напишите совместную обработку этого.

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

Например, допустим, что вы уничтожили поток после того, как он открыл файл, файл не будет закрыт до тех пор, пока приложение не завершится.

1 голос
/ 04 августа 2009

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

Я столкнулся с этим, когда пытался работать с кодом в стандартной библиотеке ( multiprocessing.manager Я смотрю на вас) с циклами, закодированными без условия выхода: приятно!

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

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