Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 3, 2014 13:04:09

gevg
Зарегистрирован: 2012-04-03
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Завершение потока

Доброго времени суток, столкнулся с такой странной на мой взгляд проблемой, и не не пойму в чем может собака зарыта быть.
Создаю с помощью модуля threading два потока, в каждом потоке выполняется один и тотже метод класса(метод цепляется телнетом и парсит выхлоп), в определенный момент времени необходимо чтобы выполнение метода было прекращено, я вне потока закрываю соединение. генерируется исключение, пишу обработку исключения вида try/except: sys.exit, из одного потока выходит успешно, а второй почему-то продолжает работу. почему?

Офлайн

#2 Фев. 3, 2014 18:05:23

gevg
Зарегистрирован: 2012-04-03
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Завершение потока

Нет предположений не у кого?

Офлайн

#3 Фев. 3, 2014 20:47:45

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Завершение потока

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

thread.daemon = True
По-моему так :)



Офлайн

#4 Фев. 3, 2014 21:53:43

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9999
Репутация: +  857  -
Профиль   Отправить e-mail  

Завершение потока

gevg
Нет предположений не у кого?
пиши код, не нужно словами



Офлайн

#5 Фев. 4, 2014 08:32:05

gevg
Зарегистрирован: 2012-04-03
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Завершение потока

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

class Client:
    def __init__(self, host, port, Numb):
        self.tdmNumb = tdmNumb
        self.telnetHost = host
        self.telnetPort = port
    def getByTelnet(self):
        try:
            self.telnetConnection = telnetlib.Telnet(self.telnetHost, self.telnetPort) #телнет соединение
        except socket.error as msg:
            main_logger.error(u'Ошибка при соединение по телнет с сервером: ' + self.telnetHost)
        print u'Анализ полученных данных'
        while 1:
            try:
                returnString = self.telnetConnection.read_until("\n")    #возвращает строку
                print returnString              
            except AttributeError:
                pass
            except EOFError:
                pass
    def cancelTelnetConnection(self):
        sys.exit()
    def __del__(self):
        self.telnetConnection.close()
monitor1 = Client("host.example", "6666", "1")
monitor2 = Client("host2.example", "7777", "2")
thread1 = threading.Thread(target=monitor1.getByTelnet)
thread2 = threading.Thread(target=monitor2.getByTelnet)
thread1.start()
thread2.start()
monitor1.cancelTelnetConnection()

Офлайн

#6 Фев. 4, 2014 08:44:59

gevg
Зарегистрирован: 2012-04-03
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Завершение потока

Разобрался, спасибо) Daemon = True помог

Офлайн

#7 Фев. 4, 2014 09:08:51

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Завершение потока

Мне думается, что правильнее и понятнее будет вот так:

import telnetlib
import threading
import time
class Client(threading.Thread):
    
    def __init__(self, host, port, numb, finished):
        super().__init__()
        self.numb = numb
        self.host = host
        self.port = port
        self.finished = finished
        self.start()
    
    def run(self):
        try:
            self.connection = telnetlib.Telnet(self.host, self.port) #телнет соединение
        except socket.error as msg:
            main_logger.error(u'Ошибка при соединение по телнет с сервером: ' + self.host)
        print u'Анализ полученных данных'
        while not finished.is_set():
            try:
                result = self.connection.read_until("\n")    #возвращает строку
                print result              
            except AttributeError:
                pass
            except EOFError:
                pass
        self.connection.close()
 
clients = (("host.example", "6666", "1"), ("host2.example", "7777", "2"))
finished = threading.Event()
threads = [Client(*(x + (finished,))) for x in clients]
time.sleep(30)
finished.set()
for thread in threads:
    thread.join()



Отредактировано pyuser (Фев. 4, 2014 09:11:21)

Офлайн

#8 Фев. 4, 2014 09:15:21

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Завершение потока

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



Офлайн

#9 Фев. 4, 2014 09:27:43

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Завершение потока

http://docs.python.org/2/library/threading.html#thread-objects

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.

Note: Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
Насколько я понял документацию, демон треды должны завершаться автоматически.



Офлайн

#10 Фев. 4, 2014 10:33:02

gevg
Зарегистрирован: 2012-04-03
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Завершение потока

pyuser, возможно и правильнее, но лично мне неособо понятнее

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version