jaraco / irc

Full-featured Python IRC library for Python.
MIT License
392 stars 87 forks source link

How to cleanly stop a reactor? #179

Open d33tah opened 3 years ago

d33tah commented 3 years ago

I'm trying to write an asynchronous client that's just trying to connect, join a channel, send a message and then quit. I looked at irccat as an example, but I am left with a reactor working while I want the rest of my program to continue outside of that flow. My workaround is that I created a multiprocessing.Process that I then terminate:

import time
import logging
import multiprocessing

import irc.client

logging.basicConfig(level='DEBUG')

def notify_thread(msg):
    client = irc.client.Reactor()
    server = client.server()
    server.connect('irc.freenode.net', 6667, 'hsldzat')

    def on_connect(connection, event):
        connection.join('##test3')

    def on_join(connection, event):
        connection.privmsg('##test3', msg)
        connection.quit()

    client.add_global_handler("welcome", on_connect)
    client.add_global_handler("join", on_join)
    client.process_forever()

def notify(msg):
    t = multiprocessing.Process(target=notify_thread, args=(msg, ))
    t.start()
    time.sleep(60)
    t.terminate()

while True:
    for i in range(3):
        notify('hello' + str(i+1))

Assuming that it's critical for my code to work synchronously and outside of the callback-based model, is there a cleaner way to use the API? Perhaps it would make sense to incorporate it into irccat example instead of doing sys.exit()?

d33tah commented 3 years ago

Another solution I came up with was to throw an exception and then catch it over process_forever. It's cleaner, but I'm still curious if there's a better way.

jaraco commented 3 years ago

One way would be to subclass Reactor and override process_forever to run until some state changes. Another would be to have your own event loop that calls reactor.process_once until a certain condition is reached.