# aiosock -- Multiprocess communication sockets for asyncio
This package wraps the [`socket`](https://docs.python.org/3/library/socket.html) lib, so that it can be used as part of the non-blocking asyncio event loop. A goal scenario is multiprocess communication with the help of coroutines, *i.e.*, combining [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) and [`asyncio`](https://docs.python.org/3/library/asyncio.html).
For example, there are two processes in a program: one is `Main_Process`, and the other is `IO_Process`. The two processes are running with respective event loops. The `Main_Process` is asynchronizedly reading messages from `IO_Process`, and once the `IO_Process` sends something to the `Main_Process`, the latter will call a `callback` function or continue executing a coroutine from the previous break point.
## Quick Start
First, install `aiosock`.
```
pip install aiosock
```
Second, import modules
```Python
import aiosock
import asyncio
```
Third, create aio-socket pair
```Python
sock1, sock2 = aiosocket.aiosockpair()
```
Forth, if you wish to use a callback function, initialize the aio-socket(s) with the function. The form of the function should be
```Python
def callback(obj_recv: Any, *args: Any): ...
```
The first argument is the object received from the other socket, and the remainder are arguments passed from where the socket is initialized. For example
```Python
def callback_print(obj_recv: Any, num: int):
print(f'{num}: {obj_recv}')
sock1.init((callback_print, 0))
```
Fifth, you may also use `await` to read something in an `async` function, rather than using a callback. For example
```Python
async def main():
obj_recv = await sock1.read()
```
Sixth, you are able to set callbacks for both read and write. the read callback is executed whenever something is received, and the write callback is executed when it is available to write. For example
```Python
def callback_print(obj_recv: Any, num: int):
print(f'{num}: {obj_recv}')
def callback_writable():
print('Now writable.')
sock1.init((callback_print, 0), callback_writable)
```
The defaut values of the callbacks are `None`.
Seventh, send any object you want, as long as the object is serializable.
```Python
sock2.send('Hello asyncio!')
```
You can call `sock2.send(...)` in another process and initialized the `sock2` in that process, so that multiple processes are able to communicate with each other.
Finally, don't forget to run the event loop, for example
```Python
asyncio.get_event_loop().run_forever()
```
Here is a complete demonstration below.
### Demo
Code:
``` Python
from multiprocessing import Process
import os
from typing import Any, Iterable, Mapping
from aiosock import AioSock, aiosockpair
import asyncio
class IO_Process(Process):
''''''
def __init__(self, sock: AioSock, group = None, name: 'str | None' = None, args: Iterable[Any] = (), kwargs: Mapping[str, Any] = {}, *, daemon: 'bool | None' = None) -> None:
super().__init__(group, None, name, daemon=daemon)
self.sock = sock
def run(self):
print(f'IO Process PID: {os.getpid()}')
self.loop = asyncio.get_event_loop()
self.sock.init(self.on_read)
self.loop.call_later(3, self.sock.write, f'[sock2 write] PID: {os.getpid()}')
self.loop.create_task(self.read())
self.loop.run_forever()
def on_read(self, obj: Any, *args):
''''''
print(obj)
print(f'[io on_read] PID: {os.getpid()}')
async def read(self):
''''''
while True:
obj = await self.sock.read()
print(f'[io await read]{str(obj)}')
print(f'[io await read] PID: {os.getpid()}')
async def main(sock: AioSock):
''''''
sock1.write(f'[sock1 write] PID: {os.getpid()}')
obj = await sock.read()
print(obj)
print(f'[main await read] PID: {os.getpid()}')
if __name__ == '__main__':
print('IO Process Read/Write, Main Process Write/Read.')
print(f'Main Process PID: {os.getpid()}')
sock1, sock2 = aiosockpair()
iop = IO_Process(sock2)
sock1.init()
iop.start()
loop = asyncio.get_event_loop()
loop.run_until_complete(main(sock1))
```
Output:
```
Main Process PID: 15408
IO Process PID: 12324
[sock1 write] PID: 15408
[io on_read] PID: 12324
[io await read][sock1 write] PID: 15408
[io await read] PID: 12324
[sock2 write] PID: 12324
[main await read] PID: 15408
```
Raw data
{
"_id": null,
"home_page": "https://github.com/bowen-xu/aiosock",
"name": "aiosock",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7.0",
"maintainer_email": "",
"keywords": "asyncio,multiprocess,socket",
"author": "Bowen XU",
"author_email": "xubowen@pku.edu.cn",
"download_url": "https://files.pythonhosted.org/packages/ca/a8/36772e7948c714bd4ec16e415d36681b9db299480bf9e61733b2cd4a4423/aiosock-1.0.6.tar.gz",
"platform": null,
"description": "# aiosock -- Multiprocess communication sockets for asyncio\n\nThis package wraps the [`socket`](https://docs.python.org/3/library/socket.html) lib, so that it can be used as part of the non-blocking asyncio event loop. A goal scenario is multiprocess communication with the help of coroutines, *i.e.*, combining [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) and [`asyncio`](https://docs.python.org/3/library/asyncio.html). \n\nFor example, there are two processes in a program: one is `Main_Process`, and the other is `IO_Process`. The two processes are running with respective event loops. The `Main_Process` is asynchronizedly reading messages from `IO_Process`, and once the `IO_Process` sends something to the `Main_Process`, the latter will call a `callback` function or continue executing a coroutine from the previous break point.\n\n## Quick Start\n\nFirst, install `aiosock`.\n\n```\npip install aiosock\n```\n\nSecond, import modules\n\n```Python\nimport aiosock\nimport asyncio\n```\n\nThird, create aio-socket pair\n```Python\nsock1, sock2 = aiosocket.aiosockpair()\n```\n\nForth, if you wish to use a callback function, initialize the aio-socket(s) with the function. The form of the function should be\n```Python\ndef callback(obj_recv: Any, *args: Any): ...\n```\nThe first argument is the object received from the other socket, and the remainder are arguments passed from where the socket is initialized. For example\n\n```Python\ndef callback_print(obj_recv: Any, num: int): \n print(f'{num}: {obj_recv}')\n\nsock1.init((callback_print, 0))\n```\n\nFifth, you may also use `await` to read something in an `async` function, rather than using a callback. For example\n\n```Python\nasync def main():\n obj_recv = await sock1.read()\n```\nSixth, you are able to set callbacks for both read and write. the read callback is executed whenever something is received, and the write callback is executed when it is available to write. For example\n\n```Python\ndef callback_print(obj_recv: Any, num: int): \n print(f'{num}: {obj_recv}')\n\ndef callback_writable():\n print('Now writable.')\n\nsock1.init((callback_print, 0), callback_writable)\n```\n\nThe defaut values of the callbacks are `None`.\n\nSeventh, send any object you want, as long as the object is serializable.\n```Python\nsock2.send('Hello asyncio!')\n```\n\nYou can call `sock2.send(...)` in another process and initialized the `sock2` in that process, so that multiple processes are able to communicate with each other.\n\nFinally, don't forget to run the event loop, for example\n\n```Python\nasyncio.get_event_loop().run_forever()\n```\n\nHere is a complete demonstration below.\n\n\n### Demo\n\nCode:\n\n``` Python\nfrom multiprocessing import Process\nimport os\nfrom typing import Any, Iterable, Mapping\nfrom aiosock import AioSock, aiosockpair\nimport asyncio\n\n\nclass IO_Process(Process):\n ''''''\n def __init__(self, sock: AioSock, group = None, name: 'str | None' = None, args: Iterable[Any] = (), kwargs: Mapping[str, Any] = {}, *, daemon: 'bool | None' = None) -> None:\n super().__init__(group, None, name, daemon=daemon)\n self.sock = sock\n\n\n def run(self):\n print(f'IO Process PID: {os.getpid()}')\n self.loop = asyncio.get_event_loop()\n self.sock.init(self.on_read)\n self.loop.call_later(3, self.sock.write, f'[sock2 write] PID: {os.getpid()}')\n self.loop.create_task(self.read())\n self.loop.run_forever()\n\n\n def on_read(self, obj: Any, *args):\n ''''''\n print(obj)\n print(f'[io on_read] PID: {os.getpid()}')\n\n\n async def read(self):\n ''''''\n while True:\n obj = await self.sock.read()\n print(f'[io await read]{str(obj)}')\n print(f'[io await read] PID: {os.getpid()}')\n\n\nasync def main(sock: AioSock):\n ''''''\n sock1.write(f'[sock1 write] PID: {os.getpid()}')\n obj = await sock.read()\n print(obj)\n print(f'[main await read] PID: {os.getpid()}')\n\n\nif __name__ == '__main__': \n print('IO Process Read/Write, Main Process Write/Read.') \n print(f'Main Process PID: {os.getpid()}')\n sock1, sock2 = aiosockpair()\n iop = IO_Process(sock2)\n sock1.init()\n iop.start()\n loop = asyncio.get_event_loop()\n loop.run_until_complete(main(sock1))\n```\n\nOutput:\n\n```\nMain Process PID: 15408\nIO Process PID: 12324\n[sock1 write] PID: 15408\n[io on_read] PID: 12324\n[io await read][sock1 write] PID: 15408\n[io await read] PID: 12324\n[sock2 write] PID: 12324\n[main await read] PID: 15408\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Multiprocess communication sockets for asyncio",
"version": "1.0.6",
"project_urls": {
"Homepage": "https://github.com/bowen-xu/aiosock"
},
"split_keywords": [
"asyncio",
"multiprocess",
"socket"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "caa836772e7948c714bd4ec16e415d36681b9db299480bf9e61733b2cd4a4423",
"md5": "706776519188e6a54b9986964392fea4",
"sha256": "8fd873cc6a794922f7b63f20d559025542debea2e377afe292e4f63b263fdf6d"
},
"downloads": -1,
"filename": "aiosock-1.0.6.tar.gz",
"has_sig": false,
"md5_digest": "706776519188e6a54b9986964392fea4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7.0",
"size": 5901,
"upload_time": "2023-09-17T17:43:43",
"upload_time_iso_8601": "2023-09-17T17:43:43.279809Z",
"url": "https://files.pythonhosted.org/packages/ca/a8/36772e7948c714bd4ec16e415d36681b9db299480bf9e61733b2cd4a4423/aiosock-1.0.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-09-17 17:43:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bowen-xu",
"github_project": "aiosock",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "aiosock"
}