Форум сайта python.su
Alex2ndrВот так с самого начала и надо было делать. Для общения с потоками нужно использовать события и Queue. Напрямую устанавливать флаги и проверять с разных потоков плохой тон, даже если язык гарантирует атомарность этих операций.
Сделал на threading.Event - вроде таких граблей нет.
Отредактировано (Июль 19, 2010 01:26:20)
Офлайн
nerijusДелал. Без переопределения join это все равно не работало. А старался использовать вариант с флагами т к “Simple is better than complex” - Если бы подощло простое решение, то зачем делать сложно?
Вот так с самого начала и надо было делать.
Офлайн
Alex2ndrС join все в порядке. Дело просто в том что join как и например socket.accept, блокирует поток и при этом не получает KeyboardInterrupt. А это исключение получает только главный поток. Так что нужно запустить цикл со sleep или join с таймаоутом (что вы практически и пытались неявно сделать переписывая сам join). Главное тут не попасть в блокировку на долго.
Делал. Без переопределения join это все равно не работало.
Alex2ndrНе спорю. Но иногда сделать все очень просто не выходит. Хотя этот случай и не из таких. Я тут невижу никаких сложностей.
т к “Simple is better than complex” - Если бы подощло простое решение, то зачем делать сложно?
Офлайн
Согласен тобой, nerijus. threading.Event тут явно правильнее обычного флага.
Если бы нужно было бы сделать АПИ не для внутреннего использования, я бы использовал property, так как это явно красивее. Но тут это уже лишнее.
Офлайн
В дополнение к этой теме еще 2 статейки(если можно так выразится):
http://habrahabr.ru/blogs/python/84629/
http://community.livejournal.com/ru_python/275027.html
После изучения этого материала и ОСОЗНАНИЯ того факта, что когда мы в Main Thread сделали join, то управление к нему не возвращается никогда (ну или очень долго - дольше чем я ждал), мне стало понятно высказывание:
nerijusТ е решение было еще проще. Вместо того, чтобы делать join просто делаем бесконечный цикл, в котором проверяем флаг/событие и тд. Пойду пробовать…
С join все в порядке. Дело просто в том что join как и например socket.accept, блокирует поток и при этом не получает KeyboardInterrupt. А это исключение получает только главный поток. Так что нужно запустить цикл со sleep или join с таймаоутом (что вы практически и пытались неявно сделать переписывая сам join). Главное тут не попасть в блокировку на долго.
Офлайн
Ненужно даже флаг в цикле проверять. Вот набросил маленький пример:
from threading import Thread
from time import sleep
class Worker(Thread):
def __init__(self):
Thread.__init__(self)
self.terminated = False
def run(self):
while not self.terminated:
sleep(1)
def terminate(self):
self.terminated = True
self.join()
if __name__ == '__main__':
worker = Worker()
worker.start()
try:
while True:
sleep(1)
except KeyboardInterrupt:
print "Ctrl-C"
worker.terminate()
print "Done"
Офлайн
Тогда такой вопрос: а если подойти архитектурно(как в соседней теме :) ) то насколько грамотен тот или иной подход? После изучения всего материала пришел к выводу, что результат в принципе получается одинаковым - т е выполнение перехватывается всеми потоками, в том числе и main thread. Разве что переопределять чужие функции, без должной причины, не хорошо…
Офлайн
Alex2ndrКогда речь идет о потоках, важно не где часть кода лежит, о который поток его выполняет. Только не уверен правильно ли я вопрос понял :)
т е выполнение перехватывается всеми потоками
Alex2ndrТут уж нужно смотреть сделаны ли эти методи как бы для расширения. Даже не знаю как тут луче объяснить… ну например переопределение Thread.run - ок, а Thread.join - плохо.
Разве что переопределять чужие функции, без должной причины, не хорошо…
Офлайн
nerijus, в твоём подходе есть одно странное недоразумение… Все нити завершаются последовательно, а не параллельно. В общем-то иногда это будет хорошей фишкой, но нам уж лучше, чтобы оно быстрее завершалось.
Архитектурно такой приём мне не нравится. Не люблю:
while True:
sleep(1)
Офлайн
ZZZА где у меня в примере ты видишь еще хотя бы один поток кроме main и worker? Для простоты я не делал никакого листа, пула и т.д. и не морочил этим себе голову.
в твоём подходе есть одно странное недоразумение… Все нити завершаются последовательно, а не параллельно.
ZZZА есть ли альтернатива когда поток ждет, ничего не делает, но при этом может получить о обработать KeyboardInterrupt? Если есть выкладывайте, сам буду рад увидеть :) Если нет, тогда предложите более элегантное решение.
Архитектурно такой приём мне не нравится. Не люблю:
Офлайн