Ĺadny brzuch
Mam dość głupi problem z wielowątkowością w pythonie, otóż piszę sobie skrypt, który będzie pobierał dane z named pipe i wyświetlał je na IRCu (planuję oczywiścię trochę większą funkcjonalność, ale w tym momencie to nie ma znaczenia). Po głębszym zastanowieniu i przestudiowaniu kodu źródłowego python-irclib doszedłem do wniosku, że nie ma innego wyjścia, niż użycie wielowątkowości - gdy irclib przechodzi do głównej pętli nie ma już innego sposobu na interakcję z botem niż za pomocą IRCa, co z wiadomych względów mi nie wystarcza.
Mój problem polega na tym, że kod co prawda działa, tj. SocketServer ładnie pobiera dane i przesyła je do IRCThread, który to wysyła dane na kanał IRC, jednak wszelkie próby ładnego zatrzymania kodu spełzają na niczym, muszę kill'ować. Jeżeli nie odpalę SocketServera to IRCThread sam w sobie daje się grzecznie wyłączyć, jeżeli odpale to nie ginie żaden. Pytanie brzmi, jak grzecznie zabić cały proces?
# -*- coding: utf-8 -*- from ircbot import SingleServerIRCBot import ircbot import threading import sys, time, logging, os logging.root.setLevel(0) #wszystkie informacje import SocketServer class MyUnixStreamServer(SocketServer.UnixStreamServer): #override - chcę mieć możliwość przesyłania danych do IRCThread przy łapaniu requesta def __init__(self, server_adress, RequestHandlerClass, ircthread): SocketServer.UnixStreamServer.__init__(self, server_adress, RequestHandlerClass) self.ircthread = ircthread class DodekBot(SingleServerIRCBot): '''IRCBot announcing about changes on special channel''' def __init__(self, server_list, nickname, realname, channel): SingleServerIRCBot.__init__(self, server_list, nickname, realname) self.nickname = nickname self.realname = realname self.server = server_list[0][0] self.port = server_list[0][1] self.channel = channel def on_welcome(self, c, e): logging.debug("Dołączam do kanału "+self.channel) c.join(self.channel) def on_join(self, c, e): logging.debug("Dołączyłem do kanału "+self.channel) def on_pubmsg(self, c, e): logging.debug("pubmsg zabija bota") self.die() def say(self, msg): self.connection.privmsg(self.channel, msg) class IRCThread(threading.Thread): def __init__(self, server_list, nickname, realname, channel): threading.Thread.__init__(self) self.bot = DodekBot([("irc.freenode.net", 6667)], "DodekBot", "Testowy bot Dodka", "#dodektest") def shutdown(self): logging.debug("Wysyłam do bota rozkaz wyłączenia sie") self.bot.ircobj.stop = True #ustalanie flagi, po której irclib się zatrzymuje, zajrzyj do patcha def run(self): logging.debug("Łączę z serwerem") self.bot.start() return class SocketThread(threading.Thread): class ReportRequestHandler(SocketServer.StreamRequestHandler): def handle(self): logging.debug("Odbieram zgłoszenie") x = self.wfile.read() self.server.ircthread.bot.say(x) def __init__(self, ircthread): threading.Thread.__init__(self) self._finished = threading.Event() if os.path.exists("/home/dodek/dodekbot.socket"): os.remove("/home/dodek/dodekbot.socket") #wywalanie starego pliku socketa self.server = MyUnixStreamServer("/home/dodek/dodekbot.socket", self.ReportRequestHandler, ircthread) def shutdown(self): logging.debug("Wysyłam do serwera rozkaz wyłączenia sie") self._finished.set() #czego to nie działa? def run(self): logging.debug("Odpalam serwer") while not self._finished.isSet(): #czego to nie działa? self.server.handle_request() if __name__=="__main__": irc = IRCThread([("irc.freenode.net", 6667)], "DodekBot", "Testowy bot Dodka", "#dodektest") server = SocketThread(irc) irc.start() server.start() lock = True while lock == True: try: irc.bot.connection._get_socket() #sprawdzam, czy juz sie polaczyl z IRCem except AttributeError: logging.debug("Nie ma socketa, spie") time.sleep(2) #sleep na 2 sekundy, az sie polaczy continue lock = False irc.bot.say("Dołączyłem do kanału.") try: while 1: time.sleep(1) except KeyboardInterrupt: logging.debug("Wchodzę do KeyboardInterrupt") irc.shutdown() irc.join() server.shutdown() server.join()
Ach, zapomniałbym - python-irclib wymaga małego patcha, bez którego nie byłbym w stanie zabić IRCThread:
--- /usr/share/python-support/python-irclib/irclib.py 2005-03-07 09:19:06.000000000 +0100 +++ irclib.py 2007-02-02 10:12:36.000000000 +0100 @@ -162,9 +162,11 @@ self.connections = [] self.handlers = {} self.delayed_commands = [] # list of tuples in the format (time, function, arguments) - + self.add_global_handler("ping", _ping_ponger, -42) + self.stop = False + def server(self): """Creates and returns a ServerConnection object.""" @@ -230,8 +232,11 @@ timeout -- Parameter to pass to process_once. """ while 1: - self.process_once(timeout) - + if self.stop != True: + self.process_once(timeout) + else: + return + def disconnect_all(self, message=""): """Disconnects all connections.""" for c in self.connections:
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
Mój problem polega na tym, że kod co prawda działa, tj. SocketServer ładnie pobiera dane i przesyła je do IRCThread, który to wysyła dane na kanał IRC, jednak wszelkie próby ładnego zatrzymania kodu spełzają na niczym, muszę kill'ować. Jeżeli nie odpalę SocketServera to IRCThread sam w sobie daje się grzecznie wyłączyć, jeżeli odpale to nie ginie żaden. Pytanie brzmi, jak grzecznie zabić cały proces?
# -*- coding: utf-8 -*- from ircbot import SingleServerIRCBot import ircbot import threading import sys, time, logging, os logging.root.setLevel(0) #wszystkie informacje import SocketServer class MyUnixStreamServer(SocketServer.UnixStreamServer): #override - chcę mieć możliwość przesyłania danych do IRCThread przy łapaniu requesta def __init__(self, server_adress, RequestHandlerClass, ircthread): SocketServer.UnixStreamServer.__init__(self, server_adress, RequestHandlerClass) self.ircthread = ircthread class DodekBot(SingleServerIRCBot): '''IRCBot announcing about changes on special channel''' def __init__(self, server_list, nickname, realname, channel): SingleServerIRCBot.__init__(self, server_list, nickname, realname) self.nickname = nickname self.realname = realname self.server = server_list[0][0] self.port = server_list[0][1] self.channel = channel def on_welcome(self, c, e): logging.debug("Dołączam do kanału "+self.channel) c.join(self.channel) def on_join(self, c, e): logging.debug("Dołączyłem do kanału "+self.channel) def on_pubmsg(self, c, e): logging.debug("pubmsg zabija bota") self.die() def say(self, msg): self.connection.privmsg(self.channel, msg) class IRCThread(threading.Thread): def __init__(self, server_list, nickname, realname, channel): threading.Thread.__init__(self) self.bot = DodekBot([("irc.freenode.net", 6667)], "DodekBot", "Testowy bot Dodka", "#dodektest") def shutdown(self): logging.debug("Wysyłam do bota rozkaz wyłączenia sie") self.bot.ircobj.stop = True #ustalanie flagi, po której irclib się zatrzymuje, zajrzyj do patcha def run(self): logging.debug("Łączę z serwerem") self.bot.start() return class SocketThread(threading.Thread): class ReportRequestHandler(SocketServer.StreamRequestHandler): def handle(self): logging.debug("Odbieram zgłoszenie") x = self.wfile.read() self.server.ircthread.bot.say(x) def __init__(self, ircthread): threading.Thread.__init__(self) self._finished = threading.Event() if os.path.exists("/home/dodek/dodekbot.socket"): os.remove("/home/dodek/dodekbot.socket") #wywalanie starego pliku socketa self.server = MyUnixStreamServer("/home/dodek/dodekbot.socket", self.ReportRequestHandler, ircthread) def shutdown(self): logging.debug("Wysyłam do serwera rozkaz wyłączenia sie") self._finished.set() #czego to nie działa? def run(self): logging.debug("Odpalam serwer") while not self._finished.isSet(): #czego to nie działa? self.server.handle_request() if __name__=="__main__": irc = IRCThread([("irc.freenode.net", 6667)], "DodekBot", "Testowy bot Dodka", "#dodektest") server = SocketThread(irc) irc.start() server.start() lock = True while lock == True: try: irc.bot.connection._get_socket() #sprawdzam, czy juz sie polaczyl z IRCem except AttributeError: logging.debug("Nie ma socketa, spie") time.sleep(2) #sleep na 2 sekundy, az sie polaczy continue lock = False irc.bot.say("Dołączyłem do kanału.") try: while 1: time.sleep(1) except KeyboardInterrupt: logging.debug("Wchodzę do KeyboardInterrupt") irc.shutdown() irc.join() server.shutdown() server.join()
Ach, zapomniałbym - python-irclib wymaga małego patcha, bez którego nie byłbym w stanie zabić IRCThread:
--- /usr/share/python-support/python-irclib/irclib.py 2005-03-07 09:19:06.000000000 +0100 +++ irclib.py 2007-02-02 10:12:36.000000000 +0100 @@ -162,9 +162,11 @@ self.connections = [] self.handlers = {} self.delayed_commands = [] # list of tuples in the format (time, function, arguments) - + self.add_global_handler("ping", _ping_ponger, -42) + self.stop = False + def server(self): """Creates and returns a ServerConnection object.""" @@ -230,8 +232,11 @@ timeout -- Parameter to pass to process_once. """ while 1: - self.process_once(timeout) - + if self.stop != True: + self.process_once(timeout) + else: + return + def disconnect_all(self, message=""): """Disconnects all connections.""" for c in self.connections: