Python类属性中的"共享列表"陷阱:为什么你的朋友成了别人的朋友?
今天给大家分享一个Python中非常容易踩坑的特性——类属性中默认值为可变对象(比如列表)时的诡异行为。
一个看似简单的例子
我们先看一个简单的Person类定义:
看起来很正常对吧?我们创建一个Person实例时,如果没有提供frients参数,就会默认使用空列表。
今天给大家分享一个Python中非常容易踩坑的特性——类属性中默认值为可变对象(比如列表)时的诡异行为。
我们先看一个简单的Person类定义:
看起来很正常对吧?我们创建一个Person实例时,如果没有提供frients参数,就会默认使用空列表。
前面文章我们使用python 实现了简单的天气查询mcp server,并使用cherry studio 和 Cline 实现了mcp server 的调用,之前是使用stdio 类型的mcp,本章看一下如何开发sse类型的mcp 服务。
sse,Server-Sent Events 是基于http 长连接的服务,以往我们在开发大模型应用的时候,由于大模型生成token 不是一次性生成的,是一个token 一个token 生成的,为了避免调用端长时间等待,会一点点的输出给调用端。
在mcp 的开发过程中,也会用到sse,但是这里的sse 和大模型输出稍微有一点不同,sse 类型的mcp 会建立一个http 监听端口,客户端在调用mcp server 时,先和mcp 建立一个长连接,之后工具的输出都是通过这个长连接发送给客户端,由于sse是单向传输,客户端只能被动的接受服务端的数据,而不能在建立连接以后再次接收客户端的数据,所以客户端在调用mcp 工具时,需要向另外一个接口发送数据。所以开发sse 的mcp 会稍微复杂一些,但是官方python sdk 中FastMCP已经做了高级封装,开发者只需要关注工具的具体实现即可。
本地stdio 类型的mcp server,通过标准的输入输出来进行数据的交互,调用端需要提前安装好环境,如python 或者 node,当然如果mcp 是一个可执行的二进制文件也可以不用安装配置环境,只是目前大部分的mcp 使用python 或者 node 进行开发的。
上一篇文章介绍了UV工具的使用,有了uv 的基础,本篇我们来看一下如何使用python开发mcp server,目前主流的 mcp 分为 stdio 和 sse,stdio 为标准输入输出,通过调用工具获取工具的输出来交互,比如你在终端输入 ping host 命令,返回ping host 的输出,SSE 稍微复杂一些,通过http 接口,返回一个sse长连接,之后工具调用输入输出遵循JSONRPC规范,通过http 调用,但是结果通过SSE长连接返回,实现起来稍微复杂一些,但是调用工具和工具配置sse会更简单一些,本篇先介绍开发简单的 stdio 类型的 mcp server。工具为调用高德地图的天气查询接口返回某地的天气情况。
最近在进行MCP server 的开发,目前主流的 mcp server 主要以node 和python 为主,其中python 主要以uv 来启动服务的,我也是由此才开始接触uv,uv 工具可以管理本地的python 版本,虚拟环境以及打包发布,还可以运行脚本,作为mcp 开发的前序基础,本文主要记录以下使用uv 开发管理python 应用的各个环节。之后在进行mcp 开发时会一直使用uv 来管理环境。
在python的整体生态中,虽然已经有很多库支持了异步调用,如可以使用httpx或者aiohttp代替requests库发起http请求,使用asyncio.sleep 代替time.sleep, 但是依然还有很多优秀的第三方库是不支持异步调用也没有可代替的库,那么如何在FastAPI中调用这种没有实现异步的库但是又不阻塞整个系统呢?
今年随着ChatGPT的爆火,也带火了一种前后端数据通信模式,使用SSE,可以让服务端一边生成内容,一边将数据返回给客户端,这样客户端可以不用等待服务端将内容全部生成。本文介绍如何在FastAPI中使用这种SSE方式返回数据,并且使用requests和aiohttp这两个第三方库调用这种SSE接口并且展示数据。
最近在学习大模型相关内容的时候,由于本地没有强大的显卡资源,很多模型是跑不起来的,但是看到阿里云机器学习平台PAI提供了一些免费的试用资源,于是准备薅一波羊毛,亲自玩一波大模型开发与微调。
接下来我将通过一系列的文章来记录一下,使用阿里云的免费资源来玩一些好玩的AIGC相关应用,主要包括ChatGLM2-6B、Llama2、通义千问、Stable Diffusion,模型微调相关的内容。
前两篇文章介绍了在golang中使用原生的rpc和使用json做为序列化工具进行rpc开发,但是它们都有着各自的缺点,原生的rpc不能跨语言,json在序列化和反序列化时效率又不高,所以本文我们再来学习一下grpc的使用,它完美的解决了它们的缺点
https://github.com/protocolbuffers/protobuf/releases
将下载的可执行文件放到对应系统的环境变量中,windows 中可以将protoc 目录添加到环境变量,mac 中可以将protoc 文件放到 /usr/local/bin 目录下,输入 protoc --version 来验证一下是否执行成功。
安装对应语言的插件, golang 中为
$GOPATH/bin/目录下生成一个protoc-gen-go 文件
编写 proto 文件
proto 文件与go 中的结构体一一对应,如果我们在go 中定义一个User的结构体
上文介绍了如何在golang 中使用原生的net/rpc 进行开发,但是使用原生的rpc有一个问题,不能跨语言,只能服务端和客户端都是golang时才可以,本文介绍如何使用json作为序列化在不同的语言间进行rpc调用。
首先我们先来修改一个服务端的代码,之前的代码中,服务端收到客户端发来的数据以后,是通过 rpc.ServeConn(conn)来处理请求的
如果要使用json来处理的话,只需要将原来的rpc.ServeConn(conn)修改为 rpc.ServeCodec(jsonrpc.NewServerCodec(conn))即可。
很早之前也了解过一些rpc, 但是心理始终接受不了这种东西,觉得http 用的好好的,为什么要那么麻烦的使用rpc? 且还要定义什么proto 文件 ,后来看了一篇文章 ,既然业内都在使用并且都快成为一种行业标准了,必然有它的优势。 以下是文章原文
go 标准库的 net\rpc 对rpc原生的支持,我们先来看一下使用go标准库是如何开发rpc应用的。
服务端开发主要分为以下四步