starbot-executor


Namestarbot-executor JSON
Version 1.2.0 PyPI version JSON
download
home_pagehttps://github.com/Starlwr/StarBotExecutor
Summary一个基于订阅发布模式的异步执行器
upload_time2023-11-22 13:18:48
maintainer
docs_urlNone
authorStarlwr
requires_python>=3.10,<4.0
licenseMIT
keywords starbot async executor
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">

# StarBotExecutor

[![PyPI](https://img.shields.io/pypi/v/starbot-executor)](https://pypi.org/project/starbot-executor)
[![Python](https://img.shields.io/badge/python-3.10%20|%203.11-blue)](https://www.python.org)
[![License](https://img.shields.io/github/license/Starlwr/StarBotExecutor)](https://github.com/Starlwr/StarBotExecutor/blob/master/LICENSE)
[![STARS](https://img.shields.io/github/stars/Starlwr/StarBotExecutor?color=yellow&label=Stars)](https://github.com/Starlwr/StarBotExecutor/stargazers)

**一个基于订阅发布模式的异步执行器**
</div>

## 特性

* 基于订阅发布模式,实现逻辑解耦
* 分级消息主题,使用灵活

## 快速开始
### 安装

```shell
pip install starbot-executor
```

### 代码框架

引入异步任务执行器 executor,执行初始化操作后即可使用

```python
from starbot_executor import executor

async def main():
    # 业务逻辑
    pass

loop = executor.init()
loop.run_until_complete(main())
loop.run_forever()
```

### 分级消息主题

消息主题为层级结构,较高层级的消息主题可同时监听到较低层级的事件,举例如下:  

使用 **@executor.on()** 装饰的方法,可监听到所有事件  
使用 **@executor.on("Message")** 装饰的方法,可监听到一级消息主题为 Message 的所有事件  
使用 **@executor.on("Message", "Test")** 装饰的方法,可监听到一级消息主题为 Message 且二级消息主题为 Test 的所有事件

### 完整示例

```python
import asyncio
import time

from starbot_executor import executor


async def main():
    # 例 1: 监听默认消息频道所有事件
    @executor.on()
    async def on_all(subjects, event):
        print(f"例 1: {subjects}: {event}")

    # 例 2: 监听默认消息频道一级消息主题为 Message 的所有事件
    @executor.on("Message")
    async def on_message(subjects, event):
        print(f"例 2: {subjects}: {event}")

    # 例 3: 监听默认消息频道一级消息主题为 Message 且二级消息主题为 Test 的所有事件
    @executor.on("Message", "Test")
    async def on_message_test(event):
        print(f"例 3: {event}")

    # 例 4: 监听消息频道为 Private 且一级消息主题为 Message 的所有事件
    @executor.on("Message", channel="Private")
    async def on_message_test():
        print(f"例 4: 私有频道事件")

    # 仅可被例 1 监听到
    executor.dispatch(None, "Other", 1)

    # 可被例 1、2 监听到
    executor.dispatch(None, "Message", "StarBot")

    # 可被例 1、2、3 监听到
    executor.dispatch(None, "Message", "Test")

    # 仅可被例 4 监听到
    executor.dispatch(None, "Message", channel="Private")

    # ——————————————————————————————————————————————————————————————————————

    # 排队执行示例
    await asyncio.sleep(1)
    await executor.create_queue_task(test(), 3)
    await executor.create_queue_task(test(), 3)
    await executor.create_queue_task(test(), 3)


async def test():
    print(f"当前时间戳: {int(time.time())}")


loop = executor.init()
loop.run_until_complete(main())
loop.run_forever()
```

输出结果:
```
例 1: ('Other', 1): None
例 1: ('Message', 'StarBot'): None
例 2: ('Message', 'StarBot'): None
例 1: ('Message', 'Test'): None
例 2: ('Message', 'Test'): None
例 3: None
例 4: 私有频道事件
当前时间戳: 1700658688
当前时间戳: 1700658691
当前时间戳: 1700658694
```

### API 文档

<details>
<summary>点击展开</summary>

#### 1. run
```
run(func: Coroutine) -> Any
```
立即调度异步任务执行,并等待返回  

Args:
* func: 异步任务

Returns:
* 异步任务返回值

#### 2. create_task
```
create_task(self, func: Coroutine) -> Task
```
调度异步任务,不等待返回

Args:
* func: 异步任务

Returns:
* Task,可用于进行 await 操作

#### 3. create_queue_task
```
create_queue_task(self, func: Coroutine, wait: Union[int, float] = 0) -> NoReturn
```
向异步任务执行队列中添加新任务

Args:
* func: 异步任务
* wait: 执行任务后的等待时间。默认:0

Returns:
* 无返回值

#### 4. create_channel
```
create_channel(self, channel: str) -> NoReturn
```
显式创建消息频道,一般情况下可省略,注册事件监听器时若指定了不存在的消息频道会自动创建

Args:
* channel: 消息频道名

Returns:
* 无返回值

#### 5. add_event_listener
```
add_event_listener(self, func: Callable, *subjects: Any, channel: str = "Default") -> NoReturn
```
注册事件监听器

Args:
* func: 回调异步函数
* subjects: 订阅消息主题,可传入多个值
* channel: 注册监听的消息频道。默认:Default

Returns:
* 无返回值

#### 6. remove_event_listener
```
remove_event_listener(self, *subjects: Any, func: Optional[Callable] = None, channel: str = "Default") -> bool
```
移除事件监听器回调函数

Args:
* subjects: 订阅消息主题,可传入多个值
* func: 要移除的回调异步函数,参数为 None 时,移除监听此消息主题的全部回调函数。默认:None
* channel: 移除监听的消息频道。默认:Default

Returns:
* 是否移除成功

#### 7. on
```
on(self, *subjects: Any, channel: str = "Default") -> Callable
```
注册事件监听器装饰器

Args:
* subjects: 订阅消息主题,可传入多个值
* channel: 注册监听的消息频道。默认:Default

Returns:
* 装饰后的函数

#### 8. dispatch
```
dispatch(self, data: Any, *subjects: Any, recursion: bool = True, channel: str = "Default") -> NoReturn
```
发布消息主题

Args:
* data: 事件附加数据
* subjects: 要发布的消息主题,可传入多个值
* recursion: 是否同时调用路径中的消息主题监听器。默认:True
* channel: 要发布的消息频道。默认:Default

Returns:
* 无返回值

</details>
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Starlwr/StarBotExecutor",
    "name": "starbot-executor",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10,<4.0",
    "maintainer_email": "",
    "keywords": "starbot,async,executor",
    "author": "Starlwr",
    "author_email": "lwr1104@qq.com",
    "download_url": "https://files.pythonhosted.org/packages/15/61/74a98790a945bd4be22031e5d44b22ac59b80b1c4c62eac95712b2b1622d/starbot_executor-1.2.0.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n\n# StarBotExecutor\n\n[![PyPI](https://img.shields.io/pypi/v/starbot-executor)](https://pypi.org/project/starbot-executor)\n[![Python](https://img.shields.io/badge/python-3.10%20|%203.11-blue)](https://www.python.org)\n[![License](https://img.shields.io/github/license/Starlwr/StarBotExecutor)](https://github.com/Starlwr/StarBotExecutor/blob/master/LICENSE)\n[![STARS](https://img.shields.io/github/stars/Starlwr/StarBotExecutor?color=yellow&label=Stars)](https://github.com/Starlwr/StarBotExecutor/stargazers)\n\n**\u4e00\u4e2a\u57fa\u4e8e\u8ba2\u9605\u53d1\u5e03\u6a21\u5f0f\u7684\u5f02\u6b65\u6267\u884c\u5668**\n</div>\n\n## \u7279\u6027\n\n* \u57fa\u4e8e\u8ba2\u9605\u53d1\u5e03\u6a21\u5f0f\uff0c\u5b9e\u73b0\u903b\u8f91\u89e3\u8026\n* \u5206\u7ea7\u6d88\u606f\u4e3b\u9898\uff0c\u4f7f\u7528\u7075\u6d3b\n\n## \u5feb\u901f\u5f00\u59cb\n### \u5b89\u88c5\n\n```shell\npip install starbot-executor\n```\n\n### \u4ee3\u7801\u6846\u67b6\n\n\u5f15\u5165\u5f02\u6b65\u4efb\u52a1\u6267\u884c\u5668 executor\uff0c\u6267\u884c\u521d\u59cb\u5316\u64cd\u4f5c\u540e\u5373\u53ef\u4f7f\u7528\n\n```python\nfrom starbot_executor import executor\n\nasync def main():\n    # \u4e1a\u52a1\u903b\u8f91\n    pass\n\nloop = executor.init()\nloop.run_until_complete(main())\nloop.run_forever()\n```\n\n### \u5206\u7ea7\u6d88\u606f\u4e3b\u9898\n\n\u6d88\u606f\u4e3b\u9898\u4e3a\u5c42\u7ea7\u7ed3\u6784\uff0c\u8f83\u9ad8\u5c42\u7ea7\u7684\u6d88\u606f\u4e3b\u9898\u53ef\u540c\u65f6\u76d1\u542c\u5230\u8f83\u4f4e\u5c42\u7ea7\u7684\u4e8b\u4ef6\uff0c\u4e3e\u4f8b\u5982\u4e0b\uff1a  \n\n\u4f7f\u7528 **@executor.on()** \u88c5\u9970\u7684\u65b9\u6cd5\uff0c\u53ef\u76d1\u542c\u5230\u6240\u6709\u4e8b\u4ef6  \n\u4f7f\u7528 **@executor.on(\"Message\")** \u88c5\u9970\u7684\u65b9\u6cd5\uff0c\u53ef\u76d1\u542c\u5230\u4e00\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Message \u7684\u6240\u6709\u4e8b\u4ef6  \n\u4f7f\u7528 **@executor.on(\"Message\", \"Test\")** \u88c5\u9970\u7684\u65b9\u6cd5\uff0c\u53ef\u76d1\u542c\u5230\u4e00\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Message \u4e14\u4e8c\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Test \u7684\u6240\u6709\u4e8b\u4ef6\n\n### \u5b8c\u6574\u793a\u4f8b\n\n```python\nimport asyncio\nimport time\n\nfrom starbot_executor import executor\n\n\nasync def main():\n    # \u4f8b 1: \u76d1\u542c\u9ed8\u8ba4\u6d88\u606f\u9891\u9053\u6240\u6709\u4e8b\u4ef6\n    @executor.on()\n    async def on_all(subjects, event):\n        print(f\"\u4f8b 1: {subjects}: {event}\")\n\n    # \u4f8b 2: \u76d1\u542c\u9ed8\u8ba4\u6d88\u606f\u9891\u9053\u4e00\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Message \u7684\u6240\u6709\u4e8b\u4ef6\n    @executor.on(\"Message\")\n    async def on_message(subjects, event):\n        print(f\"\u4f8b 2: {subjects}: {event}\")\n\n    # \u4f8b 3: \u76d1\u542c\u9ed8\u8ba4\u6d88\u606f\u9891\u9053\u4e00\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Message \u4e14\u4e8c\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Test \u7684\u6240\u6709\u4e8b\u4ef6\n    @executor.on(\"Message\", \"Test\")\n    async def on_message_test(event):\n        print(f\"\u4f8b 3: {event}\")\n\n    # \u4f8b 4: \u76d1\u542c\u6d88\u606f\u9891\u9053\u4e3a Private \u4e14\u4e00\u7ea7\u6d88\u606f\u4e3b\u9898\u4e3a Message \u7684\u6240\u6709\u4e8b\u4ef6\n    @executor.on(\"Message\", channel=\"Private\")\n    async def on_message_test():\n        print(f\"\u4f8b 4: \u79c1\u6709\u9891\u9053\u4e8b\u4ef6\")\n\n    # \u4ec5\u53ef\u88ab\u4f8b 1 \u76d1\u542c\u5230\n    executor.dispatch(None, \"Other\", 1)\n\n    # \u53ef\u88ab\u4f8b 1\u30012 \u76d1\u542c\u5230\n    executor.dispatch(None, \"Message\", \"StarBot\")\n\n    # \u53ef\u88ab\u4f8b 1\u30012\u30013 \u76d1\u542c\u5230\n    executor.dispatch(None, \"Message\", \"Test\")\n\n    # \u4ec5\u53ef\u88ab\u4f8b 4 \u76d1\u542c\u5230\n    executor.dispatch(None, \"Message\", channel=\"Private\")\n\n    # \u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\n\n    # \u6392\u961f\u6267\u884c\u793a\u4f8b\n    await asyncio.sleep(1)\n    await executor.create_queue_task(test(), 3)\n    await executor.create_queue_task(test(), 3)\n    await executor.create_queue_task(test(), 3)\n\n\nasync def test():\n    print(f\"\u5f53\u524d\u65f6\u95f4\u6233: {int(time.time())}\")\n\n\nloop = executor.init()\nloop.run_until_complete(main())\nloop.run_forever()\n```\n\n\u8f93\u51fa\u7ed3\u679c\uff1a\n```\n\u4f8b 1: ('Other', 1): None\n\u4f8b 1: ('Message', 'StarBot'): None\n\u4f8b 2: ('Message', 'StarBot'): None\n\u4f8b 1: ('Message', 'Test'): None\n\u4f8b 2: ('Message', 'Test'): None\n\u4f8b 3: None\n\u4f8b 4: \u79c1\u6709\u9891\u9053\u4e8b\u4ef6\n\u5f53\u524d\u65f6\u95f4\u6233: 1700658688\n\u5f53\u524d\u65f6\u95f4\u6233: 1700658691\n\u5f53\u524d\u65f6\u95f4\u6233: 1700658694\n```\n\n### API \u6587\u6863\n\n<details>\n<summary>\u70b9\u51fb\u5c55\u5f00</summary>\n\n#### 1. run\n```\nrun(func: Coroutine) -> Any\n```\n\u7acb\u5373\u8c03\u5ea6\u5f02\u6b65\u4efb\u52a1\u6267\u884c\uff0c\u5e76\u7b49\u5f85\u8fd4\u56de  \n\nArgs:\n* func: \u5f02\u6b65\u4efb\u52a1\n\nReturns:\n* \u5f02\u6b65\u4efb\u52a1\u8fd4\u56de\u503c\n\n#### 2. create_task\n```\ncreate_task(self, func: Coroutine) -> Task\n```\n\u8c03\u5ea6\u5f02\u6b65\u4efb\u52a1\uff0c\u4e0d\u7b49\u5f85\u8fd4\u56de\n\nArgs:\n* func: \u5f02\u6b65\u4efb\u52a1\n\nReturns:\n* Task\uff0c\u53ef\u7528\u4e8e\u8fdb\u884c await \u64cd\u4f5c\n\n#### 3. create_queue_task\n```\ncreate_queue_task(self, func: Coroutine, wait: Union[int, float] = 0) -> NoReturn\n```\n\u5411\u5f02\u6b65\u4efb\u52a1\u6267\u884c\u961f\u5217\u4e2d\u6dfb\u52a0\u65b0\u4efb\u52a1\n\nArgs:\n* func: \u5f02\u6b65\u4efb\u52a1\n* wait: \u6267\u884c\u4efb\u52a1\u540e\u7684\u7b49\u5f85\u65f6\u95f4\u3002\u9ed8\u8ba4\uff1a0\n\nReturns:\n* \u65e0\u8fd4\u56de\u503c\n\n#### 4. create_channel\n```\ncreate_channel(self, channel: str) -> NoReturn\n```\n\u663e\u5f0f\u521b\u5efa\u6d88\u606f\u9891\u9053\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\u53ef\u7701\u7565\uff0c\u6ce8\u518c\u4e8b\u4ef6\u76d1\u542c\u5668\u65f6\u82e5\u6307\u5b9a\u4e86\u4e0d\u5b58\u5728\u7684\u6d88\u606f\u9891\u9053\u4f1a\u81ea\u52a8\u521b\u5efa\n\nArgs:\n* channel: \u6d88\u606f\u9891\u9053\u540d\n\nReturns:\n* \u65e0\u8fd4\u56de\u503c\n\n#### 5. add_event_listener\n```\nadd_event_listener(self, func: Callable, *subjects: Any, channel: str = \"Default\") -> NoReturn\n```\n\u6ce8\u518c\u4e8b\u4ef6\u76d1\u542c\u5668\n\nArgs:\n* func: \u56de\u8c03\u5f02\u6b65\u51fd\u6570\n* subjects: \u8ba2\u9605\u6d88\u606f\u4e3b\u9898\uff0c\u53ef\u4f20\u5165\u591a\u4e2a\u503c\n* channel: \u6ce8\u518c\u76d1\u542c\u7684\u6d88\u606f\u9891\u9053\u3002\u9ed8\u8ba4\uff1aDefault\n\nReturns:\n* \u65e0\u8fd4\u56de\u503c\n\n#### 6. remove_event_listener\n```\nremove_event_listener(self, *subjects: Any, func: Optional[Callable] = None, channel: str = \"Default\") -> bool\n```\n\u79fb\u9664\u4e8b\u4ef6\u76d1\u542c\u5668\u56de\u8c03\u51fd\u6570\n\nArgs:\n* subjects: \u8ba2\u9605\u6d88\u606f\u4e3b\u9898\uff0c\u53ef\u4f20\u5165\u591a\u4e2a\u503c\n* func: \u8981\u79fb\u9664\u7684\u56de\u8c03\u5f02\u6b65\u51fd\u6570\uff0c\u53c2\u6570\u4e3a None \u65f6\uff0c\u79fb\u9664\u76d1\u542c\u6b64\u6d88\u606f\u4e3b\u9898\u7684\u5168\u90e8\u56de\u8c03\u51fd\u6570\u3002\u9ed8\u8ba4\uff1aNone\n* channel: \u79fb\u9664\u76d1\u542c\u7684\u6d88\u606f\u9891\u9053\u3002\u9ed8\u8ba4\uff1aDefault\n\nReturns:\n* \u662f\u5426\u79fb\u9664\u6210\u529f\n\n#### 7. on\n```\non(self, *subjects: Any, channel: str = \"Default\") -> Callable\n```\n\u6ce8\u518c\u4e8b\u4ef6\u76d1\u542c\u5668\u88c5\u9970\u5668\n\nArgs:\n* subjects: \u8ba2\u9605\u6d88\u606f\u4e3b\u9898\uff0c\u53ef\u4f20\u5165\u591a\u4e2a\u503c\n* channel: \u6ce8\u518c\u76d1\u542c\u7684\u6d88\u606f\u9891\u9053\u3002\u9ed8\u8ba4\uff1aDefault\n\nReturns:\n* \u88c5\u9970\u540e\u7684\u51fd\u6570\n\n#### 8. dispatch\n```\ndispatch(self, data: Any, *subjects: Any, recursion: bool = True, channel: str = \"Default\") -> NoReturn\n```\n\u53d1\u5e03\u6d88\u606f\u4e3b\u9898\n\nArgs:\n* data: \u4e8b\u4ef6\u9644\u52a0\u6570\u636e\n* subjects: \u8981\u53d1\u5e03\u7684\u6d88\u606f\u4e3b\u9898\uff0c\u53ef\u4f20\u5165\u591a\u4e2a\u503c\n* recursion: \u662f\u5426\u540c\u65f6\u8c03\u7528\u8def\u5f84\u4e2d\u7684\u6d88\u606f\u4e3b\u9898\u76d1\u542c\u5668\u3002\u9ed8\u8ba4\uff1aTrue\n* channel: \u8981\u53d1\u5e03\u7684\u6d88\u606f\u9891\u9053\u3002\u9ed8\u8ba4\uff1aDefault\n\nReturns:\n* \u65e0\u8fd4\u56de\u503c\n\n</details>",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u4e00\u4e2a\u57fa\u4e8e\u8ba2\u9605\u53d1\u5e03\u6a21\u5f0f\u7684\u5f02\u6b65\u6267\u884c\u5668",
    "version": "1.2.0",
    "project_urls": {
        "Homepage": "https://github.com/Starlwr/StarBotExecutor",
        "Repository": "https://github.com/Starlwr/StarBotExecutor"
    },
    "split_keywords": [
        "starbot",
        "async",
        "executor"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5deb4e1fd62739fe7696ea231c2e5181a42bd814590f2109a6254340172d1856",
                "md5": "d31bb5e91889c2e875d88f33ad77c2c3",
                "sha256": "86fc6a5e1badd2387f06f8dbf325bce64007f31a2f7e2f046f414c392c190d65"
            },
            "downloads": -1,
            "filename": "starbot_executor-1.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d31bb5e91889c2e875d88f33ad77c2c3",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10,<4.0",
            "size": 6492,
            "upload_time": "2023-11-22T13:18:46",
            "upload_time_iso_8601": "2023-11-22T13:18:46.751470Z",
            "url": "https://files.pythonhosted.org/packages/5d/eb/4e1fd62739fe7696ea231c2e5181a42bd814590f2109a6254340172d1856/starbot_executor-1.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "156174a98790a945bd4be22031e5d44b22ac59b80b1c4c62eac95712b2b1622d",
                "md5": "2ffc088dfef8d4eb77cd1d3ee0f2e142",
                "sha256": "0057e5864d3e22206cea9f6492a2093e30dc7e4a877f7cddb0c5a5d75e76c24a"
            },
            "downloads": -1,
            "filename": "starbot_executor-1.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "2ffc088dfef8d4eb77cd1d3ee0f2e142",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10,<4.0",
            "size": 9717,
            "upload_time": "2023-11-22T13:18:48",
            "upload_time_iso_8601": "2023-11-22T13:18:48.465794Z",
            "url": "https://files.pythonhosted.org/packages/15/61/74a98790a945bd4be22031e5d44b22ac59b80b1c4c62eac95712b2b1622d/starbot_executor-1.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-22 13:18:48",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Starlwr",
    "github_project": "StarBotExecutor",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "starbot-executor"
}
        
Elapsed time: 4.70211s