shizmob / pydle

An IRCv3-compliant Python 3 IRC library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Q] How do I run another loop while pydle is waiting on messages?

txtsd opened this issue · comments

commented

I'm trying to integrate pydle into another project, and I need to be able to run another loop that does synchronous things while pydle is not busy. How do I go about doing this?

Once I run

pool = pydle.ClientPool()
...
pool.handle_forever()

I'm not able to run anything else that isn't pydle.

As far as i am aware, the only way to do things while pydle is idle is to run them within the same event loop pydle uses, as async tasks.
Reason being, I am of the mindset that python's concurrency model is not condusive to parallelism thanks to the GIL.
In other languages, you could break out another thread to run a second EV / do some blocking operation concurrently, in python thats only an option if that second thread is executing non-python thanks to the GIL.
The other option is to shunt something to another process, and all the complexities that brings with.

TL;DR To execute something concurrently while Pydle is idle, just like any other python asynchronous application, either needs to be done in cooperation with the async runtime, or in another process entirely separate from the async runtime.

commented

Could you show me a small example of how I could do both?

Working in cooperation with asyncio:
To do this, all you need to do (assuming the application you are integrating with is asyncio compatable) is schedule your project's tasks on the event loop.
By default, Pydle will pull the current thread's event loop using asyncio.get_event_loop, which may be overriden by passing loop=<some event loop> to pydle's constructor.
As it uses the default loop by default, you can schedule your project's tasks using the asyncio.create_task interface, or the event_loop.enture_future interface. see https://docs.python.org/3.8/library/asyncio-task.html#asyncio.create_task

As a minimal example of this,

from pydle import Client
from your_project import your_task
import asyncio


async def main(client: pydle.Client): 
    await client.connect()   # connect pydle to the IRC server
    asyncio.create_task(your_task(...))  # create coroutine for `your_task` and schedule it for execution on the event loop
    
# entry point
if __name__ == "__main__":
    # get handle to event loop
    LOOP = asyncio.get_event_loop()
    # synchronously run main
    LOOP.run_until_complete(main())
    # submit control of the thread to the event loop.
    LOOP.run_forever()

As for the parallelism approach, i have not sufficiently read into it to provide a concrete example, but the only viable approach for a pure-python project will be multiprocessing. The threading interface is, imho, impractical and unpredictable in behavior for a pure-python application thanks to the GIL. For further reading, https://docs.python.org/3.8/library/multiprocessing.html

commented

Thanks!