Форум сайта python.su
1
Alex2ndrВот так с самого начала и надо было делать. Для общения с потоками нужно использовать события и Queue. Напрямую устанавливать флаги и проверять с разных потоков плохой тон, даже если язык гарантирует атомарность этих операций.
Сделал на threading.Event - вроде таких граблей нет.
Отредактировано (Июль 19, 2010 01:26:20)
Офлайн
0
nerijusДелал. Без переопределения join это все равно не работало. А старался использовать вариант с флагами т к “Simple is better than complex” - Если бы подощло простое решение, то зачем делать сложно?
Вот так с самого начала и надо было делать.
Офлайн
1
Alex2ndrС join все в порядке. Дело просто в том что join как и например socket.accept, блокирует поток и при этом не получает KeyboardInterrupt. А это исключение получает только главный поток. Так что нужно запустить цикл со sleep или join с таймаоутом (что вы практически и пытались неявно сделать переписывая сам join). Главное тут не попасть в блокировку на долго.
Делал. Без переопределения join это все равно не работало.
Alex2ndrНе спорю. Но иногда сделать все очень просто не выходит. Хотя этот случай и не из таких. Я тут невижу никаких сложностей.
т к “Simple is better than complex” - Если бы подощло простое решение, то зачем делать сложно?
Офлайн
26
Согласен тобой, nerijus. threading.Event тут явно правильнее обычного флага.
Если бы нужно было бы сделать АПИ не для внутреннего использования, я бы использовал property, так как это явно красивее. Но тут это уже лишнее.
Офлайн
0
В дополнение к этой теме еще 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). Главное тут не попасть в блокировку на долго.
Офлайн
1
Ненужно даже флаг в цикле проверять. Вот набросил маленький пример:
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"
Офлайн
0
Тогда такой вопрос: а если подойти архитектурно(как в соседней теме :) ) то насколько грамотен тот или иной подход? После изучения всего материала пришел к выводу, что результат в принципе получается одинаковым - т е выполнение перехватывается всеми потоками, в том числе и main thread. Разве что переопределять чужие функции, без должной причины, не хорошо…
Офлайн
1
Alex2ndrКогда речь идет о потоках, важно не где часть кода лежит, о который поток его выполняет. Только не уверен правильно ли я вопрос понял :)
т е выполнение перехватывается всеми потоками
Alex2ndrТут уж нужно смотреть сделаны ли эти методи как бы для расширения. Даже не знаю как тут луче объяснить… ну например переопределение Thread.run - ок, а Thread.join - плохо.
Разве что переопределять чужие функции, без должной причины, не хорошо…
Офлайн
26
nerijus, в твоём подходе есть одно странное недоразумение… Все нити завершаются последовательно, а не параллельно. В общем-то иногда это будет хорошей фишкой, но нам уж лучше, чтобы оно быстрее завершалось.
Архитектурно такой приём мне не нравится. Не люблю:
while True:
sleep(1)
Офлайн
1
ZZZА где у меня в примере ты видишь еще хотя бы один поток кроме main и worker? Для простоты я не делал никакого листа, пула и т.д. и не морочил этим себе голову.
в твоём подходе есть одно странное недоразумение… Все нити завершаются последовательно, а не параллельно.
ZZZА есть ли альтернатива когда поток ждет, ничего не делает, но при этом может получить о обработать KeyboardInterrupt? Если есть выкладывайте, сам буду рад увидеть :) Если нет, тогда предложите более элегантное решение.
Архитектурно такой приём мне не нравится. Не люблю:
Офлайн