ksrpc


Nameksrpc JSON
Version 0.6.11 PyPI version JSON
download
home_pageNone
SummaryKeep Simple RPC
upload_time2025-10-06 10:53:53
maintainerNone
docs_urlNone
authorNone
requires_python>=3.6
licenseMIT License Copyright (c) 2022 wukan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords rpc
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ksrpc

Keep Simple RPC。免注册远程过程调用

!!! 注意:已经迭代成第二代。第一代请参考[fastapi](https://github.com/wukan1986/ksrpc/tree/fastapi)分支

## 安全

注意:第二代只有`Baisc认证`和`导入规则列表`,其它功能无任何限制,甚至可以执行`rm -rf /`。所以强烈建议

1. 账号只给少量可信之人
2. 只部署在docker中
3. 服务不用时最好停止,或定时任务启停
4. 不要使用默认端口、默认账号、默认URL路径等
5. 导入规则列表最后一条建议`"*": False`

## 第二代 vs 第一代

### 第一代

1. 功能比较多:IP黑白名单、函数黑白名单、内网反代、数据缓存、跨语言多数据格式
2. 实际考察发现,只有内网反代功能才是大家需要的,其他功能都极少有人用
3. 缺点:由于当初没有在数据包中加入请求编号或会话编号,多人都挤同房间数据会混乱
4. pip install ksrpc<0.6.0

### 第二代

1. 考虑到大家只关注内网反代,所以决定用更专业的反代工具,如:`frp`等
2. 删减功能,只留`API`调用+`Baisc`认证+`导入规则列表`
3. 某平台中的`FastAPI`所创建的服务只要访问,`uvicorn`就崩溃,最后决定将客服端和服务端都替换成`aiohttp`
4. `async`和`sync`的互转导致系统非常混乱,清理只留`async`。但所有不改代码的`hack`功能作废
5. pip install ksrpc>=0.6.0

## 安装

```bash
pip install ksrpc -i https://mirrors.aliyun.com/pypi/simple --upgrade
# 或
pip install ksrpc -i https://pypi.org/simple --upgrade
```

## 使用

1. 服务端

```bash
# 直接运行
python -m ksrpc.run_app
# 使用配置运行
python -m ksrpc.run_app --config ./config.py
```

2. 客户端

```python
import asyncio

from ksrpc.client import RpcClient
from ksrpc.connections.http import HttpConnection

# 动态URL
URL = 'http://127.0.0.1:8080/api/v1/{time}'
USERNAME = 'admin'
PASSWORD = 'password123'


async def async_main():
    async with HttpConnection(URL, username=USERNAME, password=PASSWORD) as conn:
        demo = RpcClient('ksrpc.server.demo', conn)

        print(await demo.test())


asyncio.run(async_main())
```

## 远程调用规则

```python
# eager模式
RpcClient(..., lazy=False)
await 一个模块.零到多个模块或方法或属性.一个方法或属性(参数)
# lazy模式
RpcClient(..., lazy=True)
await 一个模块.零到多个模块或方法或属性.一个方法或属性(参数).一个方法或属性(参数).collect_async()
```

### eager模式

1. 语句后接`()`就会触发远程调用
2. `.`后的函数用来收集调用链
3. `[]`本质是`.__getitem__(item)`,内部会调整成`.__getattr__("__getitem__").__call__(item)`,会立即触发远程调用
4. 大部分情况用户代码只在最后出现`()`或`[]`,`eager`模式已经够用

### lazy模式

1. 语句后接`collect_async()`就会触发远程调用
2. `.`后的函数用来收集调用链,`()`用来收集参数
3. `[]`本质同`eager`模式,但触发要等`collect_async()`
4. 只要语句中间出现`()`或`[]`,`lazy`模式才能处理

### lazy模式特别语法

部分语句还是非常难实现

1. `__getattr__('__str__')()` # 一般都存在,就算不存在也会退回到`__repr__`
2. `__getattr__('__int__')()` # 自定义对象有可能实现,而`str`没有`__int__`

所以专门提供了一种特殊语法`.func(Self)`,它能成功运行依赖于3个条件:

1. `from ksrpc.client import Self`,然后传入`Self`参数
2. `builtins`中已经定义了`func`函数
3. `config.py`中`IMPORT_RULES`已经设置了`"builtins": True`,或没有设置`builtins`, 但设置了`"*": True`

前面两句可以简化成

1. `str(Self)`
2. `int(Self)`

建议先写原始代码测试通过,然后改成魔术方法版测试通过,最后才是远程异步版。例如:

```python
from ksrpc.client import RpcClient, Self
from ksrpc.server import demo

print(len(demo.__file__))  # 1. 在服务端或本地测试是否通过
print(demo.__file__.__len__())  # 2. 翻译成魔术方法版。看是否正常

demo1 = RpcClient('ksrpc.server.demo', conn)
demo2 = RpcClient('ksrpc.server.demo', conn, lazy=True)
print(await demo1.__file__.__len__())  # 3. 改成远程异步版。网络中传输的是`int`
print((await demo1.__file__()).__len__())  # 得到结果一样,但网络中传输的是`str`,然后本地算的`len()`
print(await demo2.__file__.__len__().collect_async())  # lazy模式,collect_async()前的代码都会在服务端计算
print(await demo2.__file__.len(Self).collect_async())  # lazy模式下的Self扩展写法

print(demo1.__doc__)  # 取的其实是RpcClient的__doc__
print(await demo1.__getattr__('__doc__')())  # 取的远程ksrpc.server.demo.__doc__
```

更多调用方式参考[examples](https://github.com/wukan1986/ksrpc/blob/main/examples)

## pyi存根文件

可以查询远程所支持的函数,可以支持`IDE`自动补全,更多细节参考[stubs](https://github.com/wukan1986/ksrpc/blob/main/stubs)

## 工作原理

1. 创建`Web`服务,接收请求后,调用服务器中的`Python`库,将结果二进制封装后返回
2. 客户端将`API`调用封装,然后向`Web`服务器请求,等待返回
3. 返回结果解包成`Python`对象
4. 反代时`frp`需要公网有服务器进行转发。当然你也可以使用其他组网工具,如`easytier`等

内网反代参考[examples_frp](https://github.com/wukan1986/ksrpc/tree/main/examples_frp)

## 传输方式

1. 先整体`zlib`压缩,然后分`chunk`传输
    - 由于整体压缩,所以可以用第三方软件直接解压
    - 浏览器和其他工具能直接识别'Content-Encoding': 'deflate'并解压
2. 先分`chunk`,每个`chunk`都分别使用`zlib`压缩再传输
    - 分块压缩,只能分块解压。第三方工具失效
    - 将大文件压缩耗时分拆了,速度显著提升

本项目的`HTTP`和`WebSocket`都使用了方案二,先分`chunk`后`zlib`压缩

## 参考项目

开发到一定阶段后才发现与`rpyc`这个免注册暴露函数的功能类似,大家也可以去学习一下

https://github.com/tomerfiliba-org/rpyc

## 声明

此库仅供学习交流,请在数据提供方的授权范围内使用。请勿向第三方转发数据
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "ksrpc",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "rpc",
    "author": null,
    "author_email": "wukan <wu-kan@163.com>",
    "download_url": "https://files.pythonhosted.org/packages/7b/65/bce70a04e6a631c4de6a8fc30eaa2ad00b668ca823c5c47effb63fa1aed3/ksrpc-0.6.11.tar.gz",
    "platform": null,
    "description": "# ksrpc\n\nKeep Simple RPC\u3002\u514d\u6ce8\u518c\u8fdc\u7a0b\u8fc7\u7a0b\u8c03\u7528\n\n!!! \u6ce8\u610f\uff1a\u5df2\u7ecf\u8fed\u4ee3\u6210\u7b2c\u4e8c\u4ee3\u3002\u7b2c\u4e00\u4ee3\u8bf7\u53c2\u8003[fastapi](https://github.com/wukan1986/ksrpc/tree/fastapi)\u5206\u652f\n\n## \u5b89\u5168\n\n\u6ce8\u610f\uff1a\u7b2c\u4e8c\u4ee3\u53ea\u6709`Baisc\u8ba4\u8bc1`\u548c`\u5bfc\u5165\u89c4\u5219\u5217\u8868`\uff0c\u5176\u5b83\u529f\u80fd\u65e0\u4efb\u4f55\u9650\u5236\uff0c\u751a\u81f3\u53ef\u4ee5\u6267\u884c`rm -rf /`\u3002\u6240\u4ee5\u5f3a\u70c8\u5efa\u8bae\n\n1. \u8d26\u53f7\u53ea\u7ed9\u5c11\u91cf\u53ef\u4fe1\u4e4b\u4eba\n2. \u53ea\u90e8\u7f72\u5728docker\u4e2d\n3. \u670d\u52a1\u4e0d\u7528\u65f6\u6700\u597d\u505c\u6b62\uff0c\u6216\u5b9a\u65f6\u4efb\u52a1\u542f\u505c\n4. \u4e0d\u8981\u4f7f\u7528\u9ed8\u8ba4\u7aef\u53e3\u3001\u9ed8\u8ba4\u8d26\u53f7\u3001\u9ed8\u8ba4URL\u8def\u5f84\u7b49\n5. \u5bfc\u5165\u89c4\u5219\u5217\u8868\u6700\u540e\u4e00\u6761\u5efa\u8bae`\"*\": False`\n\n## \u7b2c\u4e8c\u4ee3 vs \u7b2c\u4e00\u4ee3\n\n### \u7b2c\u4e00\u4ee3\n\n1. \u529f\u80fd\u6bd4\u8f83\u591a\uff1aIP\u9ed1\u767d\u540d\u5355\u3001\u51fd\u6570\u9ed1\u767d\u540d\u5355\u3001\u5185\u7f51\u53cd\u4ee3\u3001\u6570\u636e\u7f13\u5b58\u3001\u8de8\u8bed\u8a00\u591a\u6570\u636e\u683c\u5f0f\n2. \u5b9e\u9645\u8003\u5bdf\u53d1\u73b0\uff0c\u53ea\u6709\u5185\u7f51\u53cd\u4ee3\u529f\u80fd\u624d\u662f\u5927\u5bb6\u9700\u8981\u7684\uff0c\u5176\u4ed6\u529f\u80fd\u90fd\u6781\u5c11\u6709\u4eba\u7528\n3. \u7f3a\u70b9\uff1a\u7531\u4e8e\u5f53\u521d\u6ca1\u6709\u5728\u6570\u636e\u5305\u4e2d\u52a0\u5165\u8bf7\u6c42\u7f16\u53f7\u6216\u4f1a\u8bdd\u7f16\u53f7\uff0c\u591a\u4eba\u90fd\u6324\u540c\u623f\u95f4\u6570\u636e\u4f1a\u6df7\u4e71\n4. pip install ksrpc<0.6.0\n\n### \u7b2c\u4e8c\u4ee3\n\n1. \u8003\u8651\u5230\u5927\u5bb6\u53ea\u5173\u6ce8\u5185\u7f51\u53cd\u4ee3\uff0c\u6240\u4ee5\u51b3\u5b9a\u7528\u66f4\u4e13\u4e1a\u7684\u53cd\u4ee3\u5de5\u5177\uff0c\u5982\uff1a`frp`\u7b49\n2. \u5220\u51cf\u529f\u80fd\uff0c\u53ea\u7559`API`\u8c03\u7528+`Baisc`\u8ba4\u8bc1+`\u5bfc\u5165\u89c4\u5219\u5217\u8868`\n3. \u67d0\u5e73\u53f0\u4e2d\u7684`FastAPI`\u6240\u521b\u5efa\u7684\u670d\u52a1\u53ea\u8981\u8bbf\u95ee\uff0c`uvicorn`\u5c31\u5d29\u6e83\uff0c\u6700\u540e\u51b3\u5b9a\u5c06\u5ba2\u670d\u7aef\u548c\u670d\u52a1\u7aef\u90fd\u66ff\u6362\u6210`aiohttp`\n4. `async`\u548c`sync`\u7684\u4e92\u8f6c\u5bfc\u81f4\u7cfb\u7edf\u975e\u5e38\u6df7\u4e71\uff0c\u6e05\u7406\u53ea\u7559`async`\u3002\u4f46\u6240\u6709\u4e0d\u6539\u4ee3\u7801\u7684`hack`\u529f\u80fd\u4f5c\u5e9f\n5. pip install ksrpc>=0.6.0\n\n## \u5b89\u88c5\n\n```bash\npip install ksrpc -i https://mirrors.aliyun.com/pypi/simple --upgrade\n# \u6216\npip install ksrpc -i https://pypi.org/simple --upgrade\n```\n\n## \u4f7f\u7528\n\n1. \u670d\u52a1\u7aef\n\n```bash\n# \u76f4\u63a5\u8fd0\u884c\npython -m ksrpc.run_app\n# \u4f7f\u7528\u914d\u7f6e\u8fd0\u884c\npython -m ksrpc.run_app --config ./config.py\n```\n\n2. \u5ba2\u6237\u7aef\n\n```python\nimport asyncio\n\nfrom ksrpc.client import RpcClient\nfrom ksrpc.connections.http import HttpConnection\n\n# \u52a8\u6001URL\nURL = 'http://127.0.0.1:8080/api/v1/{time}'\nUSERNAME = 'admin'\nPASSWORD = 'password123'\n\n\nasync def async_main():\n    async with HttpConnection(URL, username=USERNAME, password=PASSWORD) as conn:\n        demo = RpcClient('ksrpc.server.demo', conn)\n\n        print(await demo.test())\n\n\nasyncio.run(async_main())\n```\n\n## \u8fdc\u7a0b\u8c03\u7528\u89c4\u5219\n\n```python\n# eager\u6a21\u5f0f\nRpcClient(..., lazy=False)\nawait \u4e00\u4e2a\u6a21\u5757.\u96f6\u5230\u591a\u4e2a\u6a21\u5757\u6216\u65b9\u6cd5\u6216\u5c5e\u6027.\u4e00\u4e2a\u65b9\u6cd5\u6216\u5c5e\u6027(\u53c2\u6570)\n# lazy\u6a21\u5f0f\nRpcClient(..., lazy=True)\nawait \u4e00\u4e2a\u6a21\u5757.\u96f6\u5230\u591a\u4e2a\u6a21\u5757\u6216\u65b9\u6cd5\u6216\u5c5e\u6027.\u4e00\u4e2a\u65b9\u6cd5\u6216\u5c5e\u6027(\u53c2\u6570).\u4e00\u4e2a\u65b9\u6cd5\u6216\u5c5e\u6027(\u53c2\u6570).collect_async()\n```\n\n### eager\u6a21\u5f0f\n\n1. \u8bed\u53e5\u540e\u63a5`()`\u5c31\u4f1a\u89e6\u53d1\u8fdc\u7a0b\u8c03\u7528\n2. `.`\u540e\u7684\u51fd\u6570\u7528\u6765\u6536\u96c6\u8c03\u7528\u94fe\n3. `[]`\u672c\u8d28\u662f`.__getitem__(item)`,\u5185\u90e8\u4f1a\u8c03\u6574\u6210`.__getattr__(\"__getitem__\").__call__(item)`\uff0c\u4f1a\u7acb\u5373\u89e6\u53d1\u8fdc\u7a0b\u8c03\u7528\n4. \u5927\u90e8\u5206\u60c5\u51b5\u7528\u6237\u4ee3\u7801\u53ea\u5728\u6700\u540e\u51fa\u73b0`()`\u6216`[]`\uff0c`eager`\u6a21\u5f0f\u5df2\u7ecf\u591f\u7528\n\n### lazy\u6a21\u5f0f\n\n1. \u8bed\u53e5\u540e\u63a5`collect_async()`\u5c31\u4f1a\u89e6\u53d1\u8fdc\u7a0b\u8c03\u7528\n2. `.`\u540e\u7684\u51fd\u6570\u7528\u6765\u6536\u96c6\u8c03\u7528\u94fe\uff0c`()`\u7528\u6765\u6536\u96c6\u53c2\u6570\n3. `[]`\u672c\u8d28\u540c`eager`\u6a21\u5f0f\uff0c\u4f46\u89e6\u53d1\u8981\u7b49`collect_async()`\n4. \u53ea\u8981\u8bed\u53e5\u4e2d\u95f4\u51fa\u73b0`()`\u6216`[]`\uff0c`lazy`\u6a21\u5f0f\u624d\u80fd\u5904\u7406\n\n### lazy\u6a21\u5f0f\u7279\u522b\u8bed\u6cd5\n\n\u90e8\u5206\u8bed\u53e5\u8fd8\u662f\u975e\u5e38\u96be\u5b9e\u73b0\n\n1. `__getattr__('__str__')()` # \u4e00\u822c\u90fd\u5b58\u5728\uff0c\u5c31\u7b97\u4e0d\u5b58\u5728\u4e5f\u4f1a\u9000\u56de\u5230`__repr__`\n2. `__getattr__('__int__')()` # \u81ea\u5b9a\u4e49\u5bf9\u8c61\u6709\u53ef\u80fd\u5b9e\u73b0\uff0c\u800c`str`\u6ca1\u6709`__int__`\n\n\u6240\u4ee5\u4e13\u95e8\u63d0\u4f9b\u4e86\u4e00\u79cd\u7279\u6b8a\u8bed\u6cd5`.func(Self)`\uff0c\u5b83\u80fd\u6210\u529f\u8fd0\u884c\u4f9d\u8d56\u4e8e3\u4e2a\u6761\u4ef6\uff1a\n\n1. `from ksrpc.client import Self`\uff0c\u7136\u540e\u4f20\u5165`Self`\u53c2\u6570\n2. `builtins`\u4e2d\u5df2\u7ecf\u5b9a\u4e49\u4e86`func`\u51fd\u6570\n3. `config.py`\u4e2d`IMPORT_RULES`\u5df2\u7ecf\u8bbe\u7f6e\u4e86`\"builtins\": True`\uff0c\u6216\u6ca1\u6709\u8bbe\u7f6e`builtins`, \u4f46\u8bbe\u7f6e\u4e86`\"*\": True`\n\n\u524d\u9762\u4e24\u53e5\u53ef\u4ee5\u7b80\u5316\u6210\n\n1. `str(Self)`\n2. `int(Self)`\n\n\u5efa\u8bae\u5148\u5199\u539f\u59cb\u4ee3\u7801\u6d4b\u8bd5\u901a\u8fc7\uff0c\u7136\u540e\u6539\u6210\u9b54\u672f\u65b9\u6cd5\u7248\u6d4b\u8bd5\u901a\u8fc7\uff0c\u6700\u540e\u624d\u662f\u8fdc\u7a0b\u5f02\u6b65\u7248\u3002\u4f8b\u5982\uff1a\n\n```python\nfrom ksrpc.client import RpcClient, Self\nfrom ksrpc.server import demo\n\nprint(len(demo.__file__))  # 1. \u5728\u670d\u52a1\u7aef\u6216\u672c\u5730\u6d4b\u8bd5\u662f\u5426\u901a\u8fc7\nprint(demo.__file__.__len__())  # 2. \u7ffb\u8bd1\u6210\u9b54\u672f\u65b9\u6cd5\u7248\u3002\u770b\u662f\u5426\u6b63\u5e38\n\ndemo1 = RpcClient('ksrpc.server.demo', conn)\ndemo2 = RpcClient('ksrpc.server.demo', conn, lazy=True)\nprint(await demo1.__file__.__len__())  # 3. \u6539\u6210\u8fdc\u7a0b\u5f02\u6b65\u7248\u3002\u7f51\u7edc\u4e2d\u4f20\u8f93\u7684\u662f`int`\nprint((await demo1.__file__()).__len__())  # \u5f97\u5230\u7ed3\u679c\u4e00\u6837\uff0c\u4f46\u7f51\u7edc\u4e2d\u4f20\u8f93\u7684\u662f`str`\uff0c\u7136\u540e\u672c\u5730\u7b97\u7684`len()`\nprint(await demo2.__file__.__len__().collect_async())  # lazy\u6a21\u5f0f\uff0ccollect_async()\u524d\u7684\u4ee3\u7801\u90fd\u4f1a\u5728\u670d\u52a1\u7aef\u8ba1\u7b97\nprint(await demo2.__file__.len(Self).collect_async())  # lazy\u6a21\u5f0f\u4e0b\u7684Self\u6269\u5c55\u5199\u6cd5\n\nprint(demo1.__doc__)  # \u53d6\u7684\u5176\u5b9e\u662fRpcClient\u7684__doc__\nprint(await demo1.__getattr__('__doc__')())  # \u53d6\u7684\u8fdc\u7a0bksrpc.server.demo.__doc__\n```\n\n\u66f4\u591a\u8c03\u7528\u65b9\u5f0f\u53c2\u8003[examples](https://github.com/wukan1986/ksrpc/blob/main/examples)\n\n## pyi\u5b58\u6839\u6587\u4ef6\n\n\u53ef\u4ee5\u67e5\u8be2\u8fdc\u7a0b\u6240\u652f\u6301\u7684\u51fd\u6570\uff0c\u53ef\u4ee5\u652f\u6301`IDE`\u81ea\u52a8\u8865\u5168\uff0c\u66f4\u591a\u7ec6\u8282\u53c2\u8003[stubs](https://github.com/wukan1986/ksrpc/blob/main/stubs)\n\n## \u5de5\u4f5c\u539f\u7406\n\n1. \u521b\u5efa`Web`\u670d\u52a1\uff0c\u63a5\u6536\u8bf7\u6c42\u540e\uff0c\u8c03\u7528\u670d\u52a1\u5668\u4e2d\u7684`Python`\u5e93\uff0c\u5c06\u7ed3\u679c\u4e8c\u8fdb\u5236\u5c01\u88c5\u540e\u8fd4\u56de\n2. \u5ba2\u6237\u7aef\u5c06`API`\u8c03\u7528\u5c01\u88c5\uff0c\u7136\u540e\u5411`Web`\u670d\u52a1\u5668\u8bf7\u6c42\uff0c\u7b49\u5f85\u8fd4\u56de\n3. \u8fd4\u56de\u7ed3\u679c\u89e3\u5305\u6210`Python`\u5bf9\u8c61\n4. \u53cd\u4ee3\u65f6`frp`\u9700\u8981\u516c\u7f51\u6709\u670d\u52a1\u5668\u8fdb\u884c\u8f6c\u53d1\u3002\u5f53\u7136\u4f60\u4e5f\u53ef\u4ee5\u4f7f\u7528\u5176\u4ed6\u7ec4\u7f51\u5de5\u5177\uff0c\u5982`easytier`\u7b49\n\n\u5185\u7f51\u53cd\u4ee3\u53c2\u8003[examples_frp](https://github.com/wukan1986/ksrpc/tree/main/examples_frp)\n\n## \u4f20\u8f93\u65b9\u5f0f\n\n1. \u5148\u6574\u4f53`zlib`\u538b\u7f29\uff0c\u7136\u540e\u5206`chunk`\u4f20\u8f93\n    - \u7531\u4e8e\u6574\u4f53\u538b\u7f29\uff0c\u6240\u4ee5\u53ef\u4ee5\u7528\u7b2c\u4e09\u65b9\u8f6f\u4ef6\u76f4\u63a5\u89e3\u538b\n    - \u6d4f\u89c8\u5668\u548c\u5176\u4ed6\u5de5\u5177\u80fd\u76f4\u63a5\u8bc6\u522b'Content-Encoding': 'deflate'\u5e76\u89e3\u538b\n2. \u5148\u5206`chunk`\uff0c\u6bcf\u4e2a`chunk`\u90fd\u5206\u522b\u4f7f\u7528`zlib`\u538b\u7f29\u518d\u4f20\u8f93\n    - \u5206\u5757\u538b\u7f29\uff0c\u53ea\u80fd\u5206\u5757\u89e3\u538b\u3002\u7b2c\u4e09\u65b9\u5de5\u5177\u5931\u6548\n    - \u5c06\u5927\u6587\u4ef6\u538b\u7f29\u8017\u65f6\u5206\u62c6\u4e86\uff0c\u901f\u5ea6\u663e\u8457\u63d0\u5347\n\n\u672c\u9879\u76ee\u7684`HTTP`\u548c`WebSocket`\u90fd\u4f7f\u7528\u4e86\u65b9\u6848\u4e8c\uff0c\u5148\u5206`chunk`\u540e`zlib`\u538b\u7f29\n\n## \u53c2\u8003\u9879\u76ee\n\n\u5f00\u53d1\u5230\u4e00\u5b9a\u9636\u6bb5\u540e\u624d\u53d1\u73b0\u4e0e`rpyc`\u8fd9\u4e2a\u514d\u6ce8\u518c\u66b4\u9732\u51fd\u6570\u7684\u529f\u80fd\u7c7b\u4f3c\uff0c\u5927\u5bb6\u4e5f\u53ef\u4ee5\u53bb\u5b66\u4e60\u4e00\u4e0b\n\nhttps://github.com/tomerfiliba-org/rpyc\n\n## \u58f0\u660e\n\n\u6b64\u5e93\u4ec5\u4f9b\u5b66\u4e60\u4ea4\u6d41\uff0c\u8bf7\u5728\u6570\u636e\u63d0\u4f9b\u65b9\u7684\u6388\u6743\u8303\u56f4\u5185\u4f7f\u7528\u3002\u8bf7\u52ff\u5411\u7b2c\u4e09\u65b9\u8f6c\u53d1\u6570\u636e",
    "bugtrack_url": null,
    "license": "MIT License\n        \n        Copyright (c) 2022 wukan\n        \n        Permission is hereby granted, free of charge, to any person obtaining a copy\n        of this software and associated documentation files (the \"Software\"), to deal\n        in the Software without restriction, including without limitation the rights\n        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n        copies of the Software, and to permit persons to whom the Software is\n        furnished to do so, subject to the following conditions:\n        \n        The above copyright notice and this permission notice shall be included in all\n        copies or substantial portions of the Software.\n        \n        THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n        SOFTWARE.",
    "summary": "Keep Simple RPC",
    "version": "0.6.11",
    "project_urls": null,
    "split_keywords": [
        "rpc"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "df5cc3db69cafc987b3bde53cdbe51f7d2a1aafe38baf53c8acaf340f33f5fd7",
                "md5": "eaaa00bf7d04d78db38981844c3c1ab4",
                "sha256": "18f928a14038ca569e1965ef055b4a40e96f061f0405bad7c58174610c78d4d4"
            },
            "downloads": -1,
            "filename": "ksrpc-0.6.11-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "eaaa00bf7d04d78db38981844c3c1ab4",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 33231,
            "upload_time": "2025-10-06T10:53:52",
            "upload_time_iso_8601": "2025-10-06T10:53:52.173267Z",
            "url": "https://files.pythonhosted.org/packages/df/5c/c3db69cafc987b3bde53cdbe51f7d2a1aafe38baf53c8acaf340f33f5fd7/ksrpc-0.6.11-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7b65bce70a04e6a631c4de6a8fc30eaa2ad00b668ca823c5c47effb63fa1aed3",
                "md5": "04078b25fc8a9a8960a4ab440a5be03a",
                "sha256": "77787ae291e5ea7a0d3c61a2dd572044b2475a7ead7c271caf4e4b303e33ca30"
            },
            "downloads": -1,
            "filename": "ksrpc-0.6.11.tar.gz",
            "has_sig": false,
            "md5_digest": "04078b25fc8a9a8960a4ab440a5be03a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 25516,
            "upload_time": "2025-10-06T10:53:53",
            "upload_time_iso_8601": "2025-10-06T10:53:53.302890Z",
            "url": "https://files.pythonhosted.org/packages/7b/65/bce70a04e6a631c4de6a8fc30eaa2ad00b668ca823c5c47effb63fa1aed3/ksrpc-0.6.11.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-06 10:53:53",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "ksrpc"
}
        
Elapsed time: 2.04656s