I'm designing API for a python library that accepts asynchronous input and produces the asynchronous output: various signals come in, and various signals are generated in response (there's no one-to-one relationship between input and output signals).
The input could come from a network socket/file/interactive (terminal-based) user input; or from a web framework view function. Similarly, the output may have to be sent to a socket/file/screen, or returned to a caller (in this last case, it should be buffered, and all output accumulated since the last call should be returned). The choice between different I/O channels is made once at the beginning and isn't changed while the program is running.
I assume the I/O layer uses multiple threads or processes or is asynchronous. And it calls my library functions.
What are the pros/cons of accepting as arguments two stream objects (for input and output); exposing functions that need to be called when an input is available or output is desired; using messages to communicate? Or perhaps some other approach is better?