当前位置: 首页 > news >正文

FastAPI教程I

本文参考FastAPI教程https://fastapi.tiangolo.com/zh/tutorial

第一步

import uvicorn
from fastapi import FastAPIapp = FastAPI()@app.get("/")
async def root():return {"message": "Hello World"}if __name__ == '__main__':uvicorn.run("test:app", host="127.0.0.1", port=8000, reload=True)
$ uvicorn main:app --reload
  • 导入FastAPIFastAPI是一个为你的API提供了所有功能的Python类
  • app = FastAPI()创建一个FastAPI实例,这个实例将是创建你所有API的主要交互对象。这个app同样在如下命令中被uvicorn所引用。
  • 创建一个路径操作。
    【路径】:这里的【路径】指的是从URL中第一个/起的后半部分,比如在https://example.com/items/foo中,路径是/items/foo,【路径】也通常被称为【端点】或【路由】。
    【操作】:这里的【操作】是指一种HTTP【方法】,如POST——创建数据,GET——读取数据,PUT——更新数据,DELETE——删除数据,以及更少见的几种OPTIONS,HEAD,PATCH,TRACE,在HTTP协议中,你可以使用以上的其中一种(或多种)【方法】与每个路径进行通信。
  • 定义一个路径操作装饰器@app.get("/")告诉FastAPI在它下方的函数负责处理如下访问请求:请求路径为/,使用get操作。(@something语法在Python中被称为【装饰器】,接收位于其下方的函数并且用它完成一些工作,这里是路径操作装饰器。)
  • 定义路径操作函数:位于路径操作装饰器下的函数,这里是async def root(),这个例子用的是async函数,其作用在后面讲。
  • 返回内容:可以返回一个dictlist,像strint一样的值,等等。还可以返回Pydanic模型(后面会说),还有许多其他将会自动转换为JSON的对象和模型(包括ORM对象等)。

查看运行结果

  • 打开浏览器访问 http://127.0.0.1:8000。讲看到如下的JSON相应:
{"message": "Hello World"}

交互式API文档

  • 跳转到 http://127.0.0.1:8000/docs。你将会看到自动生成的交互式API文档(由Swagger UI提供)。

可选的API文档

  • 前往 http://127.0.0.1:8000/redoc。你将会看到可选的自动生成文档(由ReDoc提供)。

路径参数

FastAPI支持以下路径模板语法定义动态路由,声明路径参数(变量)

import uvicorn
from fastapi import FastAPIapp = FastAPI()@app.get("/items/{item_id}/{go}")
async def read_item(go):return {"item_id": go}if __name__ == '__main__':uvicorn.run("test:app", host="127.0.0.1", port=8000, reload=True)

这段代码声明了相应位置上的路径参数item_idgo,并把go的值传递给路径函数的参数go

运行示例并访问http://127.0.0.1:8000/items/para1/para2可获得如下相应:

{"item_id":"para2"}

声明路径参数的类型

使用Python标准类型注释,声明路径操作函数中路径参数的类型。

from fastapi import FastAPIapp = FastAPI()@app.get("/items/{item_id}")
async def read_item(item_id: int):return {"item_id": item_id}

上例把item_id的类型声明为int

检查:类型声明将为函数提供错误检查、代码补全等编辑器支持

数据转换

运行上述声明item_id的类型为int的例子并访问 http://127.0.0.1:8000/items/3,返回的相应如下:

{"item_id":3}

可见,函数接收并返回的值是3int),不是"3"str)。FastAPI通过类型声明自动解析请求中的数据

数据校验

如果通过浏览器访问http://127.0.0.1:8000/items/foo,将会接收如下HTTP错误信息:

{"detail": [{"type": "int_parsing","loc": ["path","item_id"],"msg": "Input should be a valid integer, unable to parse string as an integer","input": "foo"}]
}

因为路径参数item_id的值("foo")的类型不是int

检查:FastAPI使用Python类型声明实现了数据校验,上面的错误清晰的指出了未通过校验的具体原因,这在开发调试与API交互的代码时非常有用。

查看文档

访问 http://127.0.0.1:8000/docs,查看自动生成的 API 文档:

Pydantic

FastAPI可以充分利用Pydanic的优势,用它在后台校验数据。

路径操作的顺序

from fastapi import FastAPIapp = FastAPI()@app.get("/users/me")
async def read_user_me():return {"user_id": "the current user"}@app.get("/users/{user_id}")
async def read_user(user_id: str):return {"user_id": user_id}

/users/me/users/{user_id}不能反过来,否则/users/me的路径会被/users/{user_id}接收。

预设值

路径操作使用Python的Enum类型接收预设的路径参数。

from enum import Enumfrom fastapi import FastAPIclass ModelName(str, Enum):alexnet = "alexnet"resnet = "resnet"lenet = "lenet"app = FastAPI()@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):if model_name is ModelName.alexnet:return {"model_name": model_name, "message": "Deep Learning FTW!"}if model_name.value == "lenet":return {"model_name": model_name, "message": "LeCNN all the images"}return {"model_name": model_name, "message": "Have some residuals"}
  • 导入Enum并创建继承自strEnum的子类。通过从str继承,API文档就能把值的类型定义为字符串,并且能正确渲染。然后创建包含固定值的类属性,这些固定值是可用的有效值。
  • 使用Enum类(ModelName)创建使用类型注解的路径参数。
  • API文档会显示预定义路径参数的可用值。
    在这里插入图片描述
  • 使用Python枚举类型:路径参数的值是枚举的元素。枚举类ModelName中的枚举元素支持比较操作(if model_name is ModelName.alexnet),使用model_name.value获取枚举值。
  • 返回枚举元素:即使嵌套在JSON请求体里(例如,dict),也可以从路径操作返回枚举元素。

包含路径的路径参数

from fastapi import FastAPIapp = FastAPI()@app.get("/files/{file_path:path}")
async def read_file(file_path: str):return {"file_path": file_path}

参数名为file_path,结尾部分的:path说明该参数应匹配路径。

查询参数

声明的参数不是路径参数时,路径操作函数会把该参数自动解释为查询参数

from fastapi import FastAPIapp = FastAPI()fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):return fake_items_db[skip : skip + limit]

查询字符串是键值对的集合,这些键值对位于URL的?之后,以&分隔。
例如,以下URL中:

http://127.0.0.1:8000/items/?skip=0&limit=2

查询参数为:skip: 0limit: 2
这些值都是URL的组成部分,因此它们的类型本应是字符串。
但声明Python类型(上例中为int)之后,这些值就会转换为声明的类型,并进行类型校验。
所有应用于路径参数的流程也适用于查询参数。

默认值

查询参数由默认值,如上例。
可以进行如下URL访问:

  • http://127.0.0.1:8000/items/
  • http://127.0.0.1:8000/items/?skip=0&limit=10
  • http://127.0.0.1:8000/items/?skip=20

可选参数

把默认值设为None即可声明可选的查询参数:

from fastapi import FastAPIapp = FastAPI()@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):if q:return {"item_id": item_id, "q": q}return {"item_id": item_id}

检查:注意,FastAPI 可以识别出 item_id 是路径参数,q 不是路径参数,而是查询参数。

查询参数类型转换

FastAPI会自动转换参数类型:

from typing import Unionfrom fastapi import FastAPIapp = FastAPI()@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False):item = {"item_id": item_id}if q:item.update({"q": q})if not short:item.update({"description": "This is an amazing item that has a long description"})return item

在本例中访问:

http://127.0.0.1:8000/items/foo?short=1

http://127.0.0.1:8000/items/foo?short=True

或short=on,short=true,short=yes或其它任意大小写形式,函数接收到的short参数都是布尔值TrueFalse同理(0,false,off,no)。

多个路径和查询参数

FastAPI可以识别同时声明的多个路径参数和查询参数,而且声明查询参数的顺序并不重要,FastAPI通过参数名进行检测:

from typing import Unionfrom fastapi import FastAPIapp = FastAPI()@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
):item = {"item_id": item_id, "owner_id": user_id}if q:item.update({"q": q})if not short:item.update({"description": "This is an amazing item that has a long description"})return item

把不是路径参数的参数(至此只有查询参数)声明为默认值,或者是吧默认值设为None,这样参数就不是必选的,否则是必选的。

上述代码可以用以下URL进行测试:

http://127.0.0.1:8000/users/2/items/item_id?q=test&short=0

将会得到这样的相应:

{"item_id":"item_id","owner_id":2,"q":"test","description":"This is an amazing item that has a long description"}

再比如:

from typing import Unionfrom fastapi import FastAPIapp = FastAPI()@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
):item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}return item

上例中有3个查询参数:needy,必选的str类型参数,skip,默认值为0int类型参数,limit,可选的int类型参数。

请求体

FastAPI使用请求体从客户端(例如浏览器)向API发送数据。

请求体是客户端发送给API的数据。响应体是API发送给客户端的数据。

API基本上肯定要发送响应体,但是客户端不一定发送请求体

使用Pydantic模型声明请求体,能充分利用它的功能和优点。

使用Pydantic声明请求体

from fastapi import FastAPI
from pydantic import BaseModelclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneapp = FastAPI()@app.post("/items/")
async def create_item(item: Item):return item

步骤如下:

  • pydantic中导入BaseModel
  • 创建数据类型:把数据模型声明为继承BaseModel的类。使用Python标准类型声明所有属性。
  • 声明请求体参数:使用与声明路径和查询参数相同的方式声明请求体,把请求体添加至路径操作,@app.post()及其下面的函数async def create_item(item: Item):...,此处请求体参数的类型为Item类型。

使用如下代码进行测试:

import requests# 定义请求的 JSON 数据
item_data = {"name": "Item1","description": "This is item 1","price": 19.99,"tax": 2.00
}# 发送 POST 请求
response = requests.post("http://localhost:8000/items/", json=item_data)# 打印返回的 JSON 数据
print(response.json())

可以看到,FastAPI接收来自测试代码的请求,返回:

{'name': 'Item1', 'description': 'This is item 1', 'price': 19.99, 'tax': 2.0}

结论

仅使用Python类型声明,FastAPI就可以

  • 以JSON形式读取请求体
  • (在必要时)把请求体转换为对应的类型
  • 校验数据:数据无效时返回错误信息,并指出错误数据的确切位置和内容
  • 把接收的数据赋值给参数item
  • 为模型生成JSON Schema,在项目中所需的位置使用

使用模型

在路径操作函数内部直接访问模型对象的属性:

from fastapi import FastAPI
from pydantic import BaseModelclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneapp = FastAPI()@app.post("/items/")
async def create_item(item: Item):item_dict = item.dict()if item.tax:price_with_tax = item.price + item.taxitem_dict.update({"price_with_tax": price_with_tax})return item_dict

用测试代码测试结果如下:

{'description': 'Mechanical keyboard','name': 'Keyboard','price': 49.99,'price_with_tax': 54.99,'tax': 5.0}

请求体+路径参数

FastAPI支持同时声明路径参数和请求体。

FastAPI能识别与路径参数匹配的函数参数,还能识别从请求体中获取的类型为Pydantic模型的函数参数。

from fastapi import FastAPI
from pydantic import BaseModelclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneapp = FastAPI()@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):return {"item_id": item_id, **item.dict()}

使用如下测试代码发送PUT请求:

import requests
from pprint import pprint# 定义要发送的 JSON 数据,符合 Item 模型的定义
item_data = {"name": "Mouse","description": "Wireless mouse","price": 19.99,"tax": 1.50
}# 定义要更新的 item_id
item_id = 1# 发送 PUT 请求
response = requests.put(f"http://localhost:8000/items/{item_id}", json=item_data)# 打印返回的 JSON 数据
pprint(response.json())

返回结果为:

{'description': 'Wireless mouse','item_id': 1,'name': 'Mouse','price': 19.99,'tax': 1.5}

请求体+路径参数+查询参数

FastAPI支持同时声明请求体路径参数查询参数

from fastapi import FastAPI
from pydantic import BaseModelclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneapp = FastAPI()@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):result = {"item_id": item_id, **item.dict()}if q:result.update({"q": q})return result

函数参数按如下规则进行识别:

  • 路径中声明了相同参数的参数,是路径参数
  • 类型是(int,float,str,bool等)单类型的参数,是查询参数
  • 类型是Pydantic模型的参数,是请求体

使用如下测试代码:

import requests
from pprint import pprint# 定义要发送的 JSON 数据,符合 Item 模型的定义
item_data = {"name": "Keyboard","description": "Mechanical keyboard","price": 49.99,"tax": 5.00
}# 定义要更新的 item_id
item_id = 1# 定义查询参数 q
q_param = "example"# 发送 PUT 请求
response = requests.put(f"http://localhost:8000/items/{item_id}?q={q_param}", json=item_data)# 打印返回的 JSON 数据
pprint(response.json())

可得到返回结果:

{'description': 'Mechanical keyboard','item_id': 1,'name': 'Keyboard','price': 49.99,'q': 'example','tax': 5.0}

查询参数和字符串校验

FastAPI允许你为参数声明额外的信息和校验。
以下面的应用程序为例:

from fastapi import FastAPIapp = FastAPI()@app.get("/items/")
async def read_items(q: str | None = None):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

查询参数q的类型为str,默认值为None,因此它是可选的。

额外的校验

我们打算添加约束条件:即使q是可选的,但只要提供了该参数,则该参数值不能超过50个字符的长度

具体步骤如下:

  • 导入Query:首先从fastapi导入Query
  • 使用Query作为默认值:将Query用作查询参数的默认值,并将它的max_length参数设置为50,由于我们必须用Query(default=None)替换默认值NoneQuery的第一个参数同样是用于定义默认值。
from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

添加更多的校验

  • 还可以添加min_length参数
  • 还可以添加正则表达式:定义一个参数值必须匹配的正则表达式
from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, min_length=3, max_length=50, pattern="^fixedquery$"),
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

声明为必需参数

当我们不需要声明额外的校验或元数据时,只需不声明默认值就可以使q参数成为必需参数,如:

q: str

但是我们现在正在用Query声明它,如:

q: Union[str, None] = Query(default=None, min_length=3)

因此,当你在使用Query且需要声明一个值是必需的时,只需不声明默认参数:

from fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: str = Query(min_length=3)):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

显式声明必需参数的方法

  • 使用(...)声明:q: str = Query(default=..., min_length=3)
  • 可以声明None为一个有效的类型,仍是必需参数:q: Union[str, None] = Query(default=..., min_length=3)
  • 使用Pydantic中的Required代替省略号...from pydantic import Requiredq: str = Query(default=Required, min_length=3)

大多数情况,隐式省略default参数就够了,通常不必使用显式声明...Required

查询参数列表/多个值

当你使用Query显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。

例如,要声明一个可在URL中出现多次的查询参数q,可以这样写:

from typing import List, Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):query_items = {"q": q}return query_items

然后输入以下网址:

http://localhost:8000/items/?q=foo&q=bar

你会在路径操作函数的函数参数q中以一个Pythonlist的形式接收到查询参数q的多个值:

{"q":["foo","bar"]}

要声明类型为list的查询参数,需要显式地使用Query,否则该参数将被解释为请求体

具有默认值的查询参数列表/多个值

可以给定默认list值:

from typing import Listfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):query_items = {"q": q}return query_items

q: List[str] = Query(default=["foo", "bar"])也可以使用list代替,这样不会检查列表的内容,如q: list = Query(default=[])

声明更多元数据

你可以添加更多有关该参数的信息。
这些信息将包含在生成的OpenAPI模式中,并由文档用户界面和外部工具所使用。

  • 添加title
from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results
  • 添加description
from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None,title="Query string",description="Query string for the items to search in the database that have a good match",min_length=3,),
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

别名参数(alias)

假设你想要查询参数为item-query,如下:

http://127.0.0.1:8000/items/?item-query=foobaritems

但是item-query不是一个有效的Python变量名称,这时可以用alias参数声明一个别名,该别名将用于在URL中查找查询参数值:

from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

弃用参数(deprecated)

假设你不再喜欢该参数。

你不得不将其保留一段时间,因为有些客户端正在使用它,但你希望文档清楚地将其展示为已弃用

那么将deprecated=True传入Query

from typing import Unionfrom fastapi import FastAPI, Queryapp = FastAPI()@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None,alias="item-query",title="Query string",description="Query string for the items to search in the database that have a good match",min_length=3,max_length=50,pattern="^fixedquery$",deprecated=True,),
):results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}if q:results.update({"q": q})return results

文档会像下面这样展示它:
在这里插入图片描述

总结

你可以为查询参数声明额外的校验和元数据。
通用的校验和元数据:

  • alias
  • title
  • description
  • deprecated

特定于字符串的校验:

  • min_length
  • max_length
  • regex

路径参数和数值校验

与使用Query为查询参数声明更多的校验和元数据的方式相同,你也可以使用Path为路径参数声明相同类型的校验和元数据。

具体步骤如下:

  • 导入Path:首先从fastapi导入Path
  • 声明元数据:可以声明与Query相同的所有参数,例如,要声明路径参数item_idtitle元数据值,可以输入item_id: Annotated[int, Path(title="The ID of the item to get")]
from typing import Annotatedfrom fastapi import FastAPI, Path, Queryapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(item_id: Annotated[int, Path(title="The ID of the item to get")],q: Annotated[str | None, Query(alias="item-query")] = None,
):results = {"item_id": item_id}if q:results.update({"q": q})return results

路径参数总是必需的

按需对参数排序

假设你想要声明一个必需的str类型查询参数q
而且你不需要为该参数声明任何其他内容,所以实际上并不需要使用Query
但是你仍然需要使用Path来声明路径参数item_id
如果你将带有【默认值】的参数放在没有【默认值】的参数之前,Python将会报错。
但是你可以对其重新排序,并将不带默认值的值(查询参数q)放到最前面。
对FastAPI来说这无关紧要。它将通过参数的名称、类型和默认值声明(QueryPath等)来检测参数,而不在乎参数的顺序。

因此可以将函数声明为:

from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):results = {"item_id": item_id}if q:results.update({"q": q})return results

还可以用*表示后面的所有参数作为关键字参数,也被称为kwargs来调用,即使它们没有默认值

from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):results = {"item_id": item_id}if q:results.update({"q": q})return results

数值校验

使用QueryPath(以及后面的其他类)可以声明字符串约束,也可以声明数值约束。如下,添加ge=1后,item_id将必须是一个大于(greater than)或等于(equal1的整数。

  • 大于等于
from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):results = {"item_id": item_id}if q:results.update({"q": q})return results
  • 大于:gt(greater than)
  • 小于等于:le(less than or equal)
from fastapi import FastAPI, Pathapp = FastAPI()@app.get("/items/{item_id}")
async def read_items(*,item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),q: str,
):results = {"item_id": item_id}if q:results.update({"q": q})return results
  • 浮点数:数值校验同样适用于float值。

请求体-多个参数

既然我们已经知道了如何使用PathQuery,下面让我们来了解一下请求体声明的更高级用法。

混合使用PathQuery和请求体参数

你可以随意混合使用PathQuery和请求体参数声明。
你还可以通过将默认值设置为None来将请求体参数声明为可选参数:

from typing import Annotatedfrom fastapi import FastAPI, Path
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],q: str | None = None,item: Item | None = None,
):results = {"item_id": item_id}if q:results.update({"q": q})if item:results.update({"item": item})return results

多个请求体参数

from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass User(BaseModel):username: strfull_name: str | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User):results = {"item_id": item_id, "item": item, "user": user}return results

在上面的情况下,FastAPI将注意到该函数中有多个请求体参数(两个Pydantic模型参数)。因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2},"user": {"username": "dave","full_name": "Dave Grohl"}
}

FastAPI将自动对请求中的数据进行转换,因此item参数将接收指定的内容,user参数也是如此。它将执行对复合数据的校验,并且像现在这样为OpenAPI模式和自动化文档对其进行记录。

请求体中的单一值(Body)

与使用QueryPath为查询参数和路径参数定义额外数据的方式相同,FastAPI提供了一个同等的Body,例如上面的模型,除了itemuser之外,还想在同一请求体中具有另一个键importance,如果按原样来声明它,因为它是一个单一值,FastAPI将假定它是一个查询参数。但是你可以使用Body指示FastAPI将其作为请求体的另一个键进行处理。

from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass User(BaseModel):username: strfull_name: str | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
):results = {"item_id": item_id, "item": item, "user": user, "importance": importance}return results

在这种情况下,FastAPI将期望这样的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2},"user": {"username": "dave","full_name": "Dave Grohl"},"importance": 5
}

多个请求体参数和查询参数

除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。
由于默认情况下单一值被解释为查询参数,因此你不必显式地添加Query

from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass User(BaseModel):username: strfull_name: str | None = None@app.put("/items/{item_id}")
async def update_item(*,item_id: int,item: Item,user: User,importance: Annotated[int, Body(gt=0)],q: str | None = None,
):results = {"item_id": item_id, "item": item, "user": user, "importance": importance}if q:results.update({"q": q})return results

嵌入单个请求体参数(Body(embed=True))

假设你只有一个来自Pydantic模型Item的请求体参数item
默认情况下,FastAPI将直接期望这样的请求体。
但是,如果你希望它期望一个拥有item键并在值中包含模型内容的JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的Body参数embed

item: Item = Body(embed=True)
from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):results = {"item_id": item_id, "item": item}return results

在这种情况下,FastAPI将期望像这样的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2}
}

而不是:

{"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2
}

总结

你可以添加多个请求体参数到路径操作函数中,即使一个请求只能有一个请求体。

但是 FastAPI 会处理它,在函数中为你提供正确的数据,并在路径操作中校验并记录正确的模式。

你还可以声明将作为请求体的一部分所接收的单一值。

你还可以指示 FastAPI 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。

请求体-字段(Field)

与在路径操作函数中使用QueryPathBody声明校验与元数据的方式一样,可以使用Pydantic的Field在Pydantic模型内部声明校验和元数据。

具体步骤如下:

  • 导入Field:首先从Pydantic中导入Field
  • 声明模型属性:使用Field定义模型的属性。
from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModel, Fieldapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Field(default=None, title="The description of the item", max_length=300)price: float = Field(gt=0, description="The price must be greater than zero")tax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):results = {"item_id": item_id, "item": item}return results

Field的工作方式和QueryPathBody相同,参数也相同。

请求体-嵌套类型

使用FastAPI,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。

List字段

你可以将一个属性定义为拥有子元素的类型。例如Pythonlist

from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: list = []@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

这将使tags成为一个由元素组成的列表。不过它没有声明每个元素的类型。

具有子类型的List字段

但是Python有一种特定的方法来声明具有子类型的列表:

具体步骤如下:

  • 声明具有子类型的List:从typing模块导入它们,使用方括号[]将子类型作为【类型参数】传入。
  • 在我们的示例中,我们可以将tags明确地指定为一个【字符串列表】。
from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: list[str] = []@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

Set类型

标签不应该重复,所以用Settag声明为一个由str组成的set

from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

这样,即使收到带有重复数据的请求,这些数据也会被转换为一组唯一项。

而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。

并且还会被相应地标注/记录文档。

嵌套类型

Pydantic模型的每个属性都具有类型。但是这个类型本身可以是另一个Pydantic模型。因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的JSON对象。

例如:

  • 定义一个Image模型
  • Image模型用作一个属性的类型
from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Image(BaseModel):url: strname: strclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()image: Image | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

这意味着FastAPI将期望类似于以下内容的请求体:

{"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2,"tags": ["rock", "metal", "bar"],"image": {"url": "http://example.com/baz.jpg","name": "The Foo live"}
}

特殊的类型和校验

除了普通的单一值类型(如strintfloat等)外,你还可以使用从str继承的更复杂的单一值类型。

要了解所有的可用选项,查看来自Pydantic的外部类型的文档。

例如,在Image模型中我们有一个url字段,我们可以把它声明为Pydantic的HttpUrl,而不是str

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: strclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()image: Image | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

该字符串将被检查是否为有效的URL,并在JSON Schema/OpenAPI文档中进行记录。

带有一组子模型的属性

你还可以将Pydantic模型用作listset等的子模型:

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: strclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()images: list[Image] | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

这将期望(转换,校验,记录文档等)下面这样的JSON请求体:

{"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2,"tags": ["rock","metal","bar"],"images": [{"url": "http://example.com/baz.jpg","name": "The Foo live"},{"url": "http://example.com/dave.jpg","name": "The Baz"}]
}

深度嵌套模型

你可以定义任意深度的嵌套模型:

from typing import Unionfrom fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: strclass Item(BaseModel):name: strdescription: Union[str, None] = Noneprice: floattax: Union[float, None] = Nonetags: set[str] = set()images: Union[list[Image], None] = Noneclass Offer(BaseModel):name: strdescription: Union[str, None] = Noneprice: floatitems: list[Item]@app.post("/offers/")
async def create_offer(offer: Offer):return offer

纯列表请求体

如果你期望的JSON请求体的最外层是一个JSONarray(即Python list),则可以在路径操作函数的参数中声明此类型,就像声明Pydantic模型一样:

images: List[Image]

例如:

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: str@app.post("/images/multiple/")
async def create_multiple_images(images: list[Image]):return images

任意dict构成的请求体

你也可以将请求体声明为使用某类型的键和其他类型值的dict
无需事先知道有效的字段/属性(在使用Pydantic模型的场景)名称是什么。
如果你想接收一些尚且未知的键,这将很有用。

其他有用的场景是当你想要接收其他类型的键时,例如int,如下,你将接受任意键为int类型并且值为float类型的dict

from fastapi import FastAPIapp = FastAPI()@app.post("/index-weights/")
async def create_index_weights(weights: dict[int, float]):return weights

JSON仅支持将str作为键,但是Pydantic具有自动转换数据的功能。这意味着,即使你的API客户端只能将字符串作为键发送,只要这些字符串内容仅包含整数,Pydantic就会对其进行转换并校验。然后你接收的名为weightsdict实际上将具有int类型的键和float类型的值。

模式的额外信息-例子

你可以在JSON模式中定义额外的信息。
一个常见的用例是添加一个将在文档中显示的example
有几种方法可以声明额外的JSON模式信息。

Pydantic schema_extra

你可以使用Configschema_extra为Pydantic模型声明一个示例,如Pydantic文档:定制Schema中所述。

from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonemodel_config = {"json_schema_extra": {"examples": [{"name": "Foo","description": "A very nice Item","price": 35.4,"tax": 3.2,}]}}@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

这些额外的信息将按原样添加到输出的JSON模式中。

Field的附加参数

FieldPathQueryBody和其他你之后将会看到的工厂函数,你可以为JSON模式声明额外信息,你也可以通过给工厂函数传递其他的任意参数来给JSON模式声明额外信息,比如增加example

from fastapi import FastAPI
from pydantic import BaseModel, Fieldapp = FastAPI()class Item(BaseModel):name: str = Field(examples=["Foo"])description: str | None = Field(default=None, examples=["A very nice Item"])price: float = Field(examples=[35.4])tax: float | None = Field(default=None, examples=[3.2])@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):results = {"item_id": item_id, "item": item}return results

传递的那些额外参数不会添加任何验证,只会添加注释,用于文档的目的。

Body额外参数

from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int,item: Annotated[Item,Body(examples=[{"name": "Foo","description": "A very nice Item","price": 35.4,"tax": 3.2,}],),],
):results = {"item_id": item_id, "item": item}return results

额外数据类型

到目前为止,一直在使用常见的数据类型,如:

  • int
  • float
  • str
  • bool
    但是也可以使用更复杂的数据类型。

其他数据类型

  • UUID:
    一种标准的 “通用唯一标识符” ,在许多数据库和系统中用作ID。
    在请求和响应中将以 str 表示。
  • datetime.datetime:
    一个 Python datetime.datetime.
    在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 2008-09-15T15:53:00+05:00.
  • datetime.date:
    Python datetime.date.
    在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 2008-09-15.
  • datetime.time:
    一个 Python datetime.time.
    在请求和响应中将表示为 ISO 8601 格式的 str ,比如: 14:23:55.003.
  • datetime.timedelta:
    一个 Python datetime.timedelta.
    在请求和响应中将表示为 float 代表总秒数。
    Pydantic 也允许将其表示为 “ISO 8601 时间差异编码”, 查看文档了解更多信息。
  • frozenset:
    在请求和响应中,作为 set 对待:
    在请求中,列表将被读取,消除重复,并将其转换为一个 set
    在响应中 set 将被转换为 list
    产生的模式将指定那些 set 的值是唯一的 (使用 JSON 模式的 uniqueItems)。
  • bytes:
    标准的 Python bytes
    在请求和响应中被当作 str 处理。
    生成的模式将指定这个 strbinary “格式”。
  • Decimal:
    标准的 Python Decimal
    在请求和响应中被当做 float 一样处理。
    您可以在这里检查所有有效的pydantic数据类型: Pydantic data types.

例子

from datetime import datetime, time, timedelta
from typing import Annotated
from uuid import UUIDfrom fastapi import Body, FastAPIapp = FastAPI()@app.put("/items/{item_id}")
async def read_items(item_id: UUID,start_datetime: Annotated[datetime, Body()],end_datetime: Annotated[datetime, Body()],process_after: Annotated[timedelta, Body()],repeat_at: Annotated[time | None, Body()] = None,
):start_process = start_datetime + process_afterduration = end_datetime - start_processreturn {"item_id": item_id,"start_datetime": start_datetime,"end_datetime": end_datetime,"process_after": process_after,"repeat_at": repeat_at,"start_process": start_process,"duration": duration,}

相关文章:

FastAPI教程I

本文参考FastAPI教程https://fastapi.tiangolo.com/zh/tutorial 第一步 import uvicorn from fastapi import FastAPIapp FastAPI()app.get("/") async def root():return {"message": "Hello World"}if __name__ __main__:uvicorn.run(&quo…...

如何在 HTML 中实现响应式设计以适应不同设备的屏幕尺寸?

要在HTML中实现响应式设计以适应不同设备的屏幕尺寸,可以使用CSS媒体查询和流动布局。 以下是实现响应式设计的一些关键步骤: 使用CSS媒体查询:CSS媒体查询允许根据屏幕尺寸和设备特性应用不同的CSS样式。通过在CSS中使用media规则&#xf…...

【基础篇】第1章 Elasticsearch 引言

1.1 Elasticsearch简介 1.1.1 基本概念 Elasticsearch,一个开源的分布式搜索引擎,以其强大的搜索能力和实时数据分析能力,在大数据时代脱颖而出。它基于Apache Lucene库构建,旨在提供高效、可扩展且易于使用的全文检索解决方案。…...

在区块链技术广泛应用的情况下,C 语言如何在区块链的底层开发中发挥更有效的作用,提高性能和安全性?

C语言在区块链底层开发中发挥着重要的作用,可以提高性能和安全性。具体可以从以下几个方面进行优化: 性能优化:C语言是一种高效的编程语言,可以直接访问内存和硬件资源。在区块链底层开发中,使用C语言可以更好地利用底…...

量化投资 日周月报 2024-06-28

文章 深度学习在量化交易中的应用:在BigQuant量化交易平台的文章中,探讨了深度学习在量化交易中,特别是在因子挖掘方面的应用。文章提到,随着传统线性模型的潜力逐渐枯竭,非线性模型逐渐成为量化交易的主要探索方向。深度学习因其对非线性关系的拟合能力,在量化交易中展现…...

基于 Paimon 的袋鼠云实时湖仓入湖实战剖析

在当今数据驱动的时代,企业对数据的实施性能力提出了前所未有的高要求。为了应对这一挑战,构建高效、灵活且可扩展的实时湖仓成为数字化转型的关键。本文将深入探讨袋鼠云数栈如何通过三大核心实践——ChunJun 融合 Flink CDC、MySQL 一键入湖至 Paimon …...

IPython相关了解

一、什么是 IPython? 1.1 简单理解 IPython IPython 是一种增强的 Python 交互式解释器,它可以让你更方便地编写、调试和运行 Python 代码。你可以把它想象成一个比普通 Python 解释器更聪明、功能更丰富的工具,非常适合用来进行数据探索、…...

华为面试题及答案——机器学习(二)

21. 如何评价分类模型的优劣? (1)模型性能指标 准确率(Accuracy): 定义:正确分类的样本数与总样本数之比。适用:当各类样本的数量相对均衡时。精确率(Precision): 定义:预测为正类的样本中实际为正类的比例。适用:当关注假阳性错误的成本较高时(例如垃圾邮件检测…...

PlatformIO开发环境

PlatformIO是一个开源的生态系统,用于构建物联网应用,它支持多种微控制器(MCU)和硬件开发板,并且与各种IDE集成良好,如VSCode, Atom等,使得跨平台的固件开发变得更加简单和高效。 ### 平台介绍…...

In install.packages(“devtools“, verbose = TRUE) :

错误于curl::curl_download("https://r-lib.github.io/gert/libgit2-1.1.0.x86_64_legacy-linux.tar.gz", : Timeout was reached: [] Connection timed out after 10004 milliseconds 停止执行 Using PKG_CFLAGS Using PKG_LIBS-lgit2 ----------------------------…...

计算机网络 访问控制列表以及NAT

一、理论知识 1. 单臂路由 单臂路由是一种在路由器上配置多个子接口的方法,每个子接口代表不同的 VLAN,用于在一个物理接口上支持多 VLAN 通信。此方法使得不同 VLAN 之间可以通过路由器进行通信。 2. NAT (网络地址转换) NAT 是一种在私有网络和公共…...

使用Oracle IMP导入数据

使用Oracle IMP导入数据 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们来聊一聊如何使用Oracle的IMP工具来导入数据。 一、什么是Oracle IMP Oracle…...

C++ 100 之 容器插入和删除

vector插入和删除操作 insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele. push_back(ele); //尾部插入元素ele pop_back();//删除最后一个元素 erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素 erase(c…...

提升 Selenium 测试稳定性的秘诀:深入理解等待 API 的使用

目录 为什么需要等待Selenium 等待 API 简介隐式等待显式等待Fluent Wait等待策略的选择示例代码总结 正文 1. 为什么需要等待 在 Web 自动化测试中,等待是一个关键因素。网络应用通常是动态的,页面加载时间、元素的显示时间都可能不同步。直接操作这…...

Python-算法编程100例-滑动窗口(入门级)

题目1:最大连续1的个数(简单) 给定一个二进制数组 nums , 计算其中最大连续 1 的个数。 解答:前缀和双指针 # 给定一个二进制数组 nums , 计算其中最大连续 1 的个数。 from typing import Listclass So…...

ffmpeg使用mjpeg把yuvj420p编码为jpg图像

version #define LIBAVUTIL_VERSION_MAJOR 58 #define LIBAVUTIL_VERSION_MINOR 12 #define LIBAVUTIL_VERSION_MICRO 100 node 不使用AVOutputFormat code void CFfmpegOps::EncodeYUVJ420pToMJPEG(const char* infile, const char* width_str, const char* height_s…...

龙迅#LT6911GXC支持HDMI2.1转MIPI/4PORT LVDS应用功能,分辨率高达8K30HZ/4K120HZ压缩格式。

1. 描述 该LT6911GXC是一款高性能HD-DVI2.1转MIPI或LVDS芯片,适用于VR/显示应用。 HDCP RX作为HDCP中继器的上游,可以与其他芯片的HDCP TX配合实现中继器功能。 对于 HD-DVI2.1 输入,LT6911GXC可以配置为 3/4 通道。 对于MIPI输出&#xff0c…...

.NET 6.0 Web API项目中实现基于Token的身份验证

本文以一个完整的示例,展示如何在.NET 6.0 Web API项目中实现基于Token的身份验证。这个例子包括了如何创建和验证JWT Token,以及如何在控制器中使用这些Token。 步骤 1: 创建Web API项目 首先,用Visual Studio 2022创建一个基于.NET6.0的 …...

Java常用对象的快速初始化

在Java中,有多种方式来快速初始化各种常用对象,如字符串数组(String[]),集合列表(List),映射表(Map),以及集合(Set)。不同…...

逻辑回归模型模拟实现:从零开始

引言 逻辑回归是一种用于二分类问题的机器学习算法。尽管它的名字中有“回归”,但它实际上是用于分类的。在本文中,我们将通过模拟数据来演示逻辑回归模型的实现。 逻辑回归简介 逻辑回归通过使用逻辑函数(通常是Sigmoid函数)将…...

Docker基本使用和认识

目录 基本使用 镜像仓库 镜像操作 Docker 如何实现镜像 1) namespace 2) cgroup 3) LXC Docker常见的网络类型 bridge网络如何实现 基本使用 镜像仓库 镜像仓库登录 1)docker login 后面不指定IP地址,则默认登录到 docker hub 上 退出 2)docker logo…...

Halcon 文本文件操作,形态学

一文件的读写 *******************************************************向文本文件写入字符串内容*************************************************************read_image (Image, fabrik)threshold (Image, Region, 0, 120)area_center (Region, Area, Row, Column)open_…...

【鸿蒙】稍微理解一下Stage模型

鸿蒙的Stage模型是HarmonyOS多端统一的应用开发框架中的一个核心概念,用于描述应用的界面层次结构和组件之间的关系。下面将详细解析Stage模型的主要组成部分和特点: 模型组成: UIAbility组件:这是应用中负责绘制用户界面的组件&a…...

毕业答辩制作PPT【攻略】

毕业答辩制作PPT【攻略】 前言版权毕业答辩制作PPT【攻略】一、WPS AI 15天免费会员二、AI文档生成PPT三、修改完善PPT 最后 前言 2024-06-14 23:43:05 以下内容源自《【攻略】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN…...

深入解析npm install --save-dev:开发依赖管理的艺术

npm(Node Package Manager)是JavaScript编程语言的包管理器,用于管理项目中的依赖关系。在开发过程中,合理地管理依赖是保证项目可维护性和可扩展性的关键。npm install命令是npm中最常用的命令之一,而--save-dev参数则…...

福布斯 AI 50 榜单中唯一开源向量数据库:Weaviate

本篇文章,聊聊福布斯全球网站前俩月发布的 2023 AI 50 榜单中的唯一一个开源的向量数据库:Weaviate。 它在数据持久化和容错性上表现非常好、支持混合搜索、支持水平扩展,同时又保持了轻量化。官方主打做 AI 时代的原生数据库,减…...

信息学奥赛初赛天天练-38-CSP-J2021阅读程序-约数个数、约数和、埃氏筛法、欧拉筛法筛素数应用

PDF文档公众号回复关键字:20240628 2021 CSP-J 阅读程序3 1阅读程序(判断题1.5分 选择题3分 共计40分 ) 01 #include<stdio.h> 02 using namespace std; 03 04 #define n 100000 05 #define N n1 06 07 int m; 08 int a[N],b[N],c[N],d[N]; 09 int f[N],g[N]; 10 11 …...

第100+13步 ChatGPT学习:R实现决策树分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言&#xff0c;不想学Python咯。 答曰&#xff1a;可&#xff01;用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了&#xff0c;就帮各位搬运一下吧。 二、R代码实现决策树分类 &#xff08;…...

Hi3861 OpenHarmony嵌入式应用入门--LiteOS MessageQueue

CMSIS 2.0接口中的消息&#xff08;Message&#xff09;功能主要涉及到实时操作系统&#xff08;RTOS&#xff09;中的线程间通信。在CMSIS 2.0标准中&#xff0c;消息通常是通过消息队列&#xff08;MessageQueue&#xff09;来进行处理的&#xff0c;以实现不同线程之间的信息…...

ffmpeg编码图象时报错Invalid buffer size, packet size * < expected frame_size *

使用ffmpeg将单个yuv文件编码转为jpg或其他图像格式时&#xff0c;报错&#xff1a; Truncating packet of size 11985408 to 3585 [rawvideo 0x1bd5390] Packet corrupt (stream 0, dts 1). image_3264_2448_0.yuv: corrupt input packet in stream 0 [rawvideo 0x1bd7c60…...

解决类重复的问题

1.针对AndroidX 类重复问题 解决办法&#xff1a; android.useAndroidXtrue android.enableJetifiertrue2.引用其他sdk出现类重复的问题解决办法&#xff1a;configurations {all { // You should exclude one of them not both of themexclude group: "com.enmoli"…...

使用 shell 脚本 统计app冷启动耗时

下面是一个 shell 脚本&#xff0c;它使用 参数将包名称作为参数--app&#xff0c;识别相应应用程序进程的 PID&#xff0c;使用 终止该进程adb shell kill&#xff0c;最后使用 重新启动该应用程序adb shell am start&#xff1a; #!/bin/bash# Check if package name is pro…...

使用容器部署redis_设置配置文件映射到本地_设置存储数据映射到本地_并开发java应用_连接redis---分布式云原生部署架构搭建011

可以看到java应用的部署过程,首先我们要准备一个java应用,并且我们,用docker,安装一个redis 首先我们去start.spring.io 去生成一个简单的web项目,然后用idea打开 选择以后下载 放在这里,然后我们去安装redis 在公共仓库中找到redis . 可以看到它里面介绍说把数据放到了/dat…...

第五节:如何使用其他注解方式从IOC中获取bean(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;上节我们实践了通过Bean方式声明Bean配置。咱们这节通过Component和ComponentScan方式实现一个同样功能。这节实现的效果是从IOC中加载Bean对象&#xff0c;并且将Bean的属性打印到控制台。 第一步&#xff1a;创建pojo实体类studen…...

Paragon NTFS与Tuxera NTFS有何区别 Mac NTFS 磁盘读写工具选哪个好

macOS系统虽然以稳定、安全系数高等优点著称&#xff0c;但因其封闭性&#xff0c;不能对NTFS格式磁盘写入数据常被人们诟病。优质的解决方案是使用磁盘管理软件Paragon NTFS for Mac&#xff08;点击获取激活码&#xff09;和Tuxera NTFS&#xff08;点击获取激活码&#xff0…...

EtherCAT主站IGH-- 2 -- IGH之coe_emerg_ring.h/c文件解析

EtherCAT主站IGH-- 2 -- IGH之coe_emerg_ring.h/c文件解析 0 预览一 该文件功能coe_emerg_ring.c 文件功能函数预览 二 函数功能介绍coe_emerg_ring.c 中主要函数的作用1. ec_coe_emerg_ring_init2. ec_coe_emerg_ring_clear3. ec_coe_emerg_ring_size4. ec_coe_emerg_ring_pus…...

psensor 的手势功能

psensor 的手势功能的移植过程 有时间再来写下...

使用 nvm 管理 Node 版本及 pnpm 安装

文章目录 GithubWindows 环境Mac/Linux 使用脚本进行安装或更新Mac/Linux 环境变量nvm 常用命令npm 常用命令npm 安装 pnpmNode 历史版本 Github https://github.com/nvm-sh/nvm Windows 环境 https://nvm.uihtm.com/nvm.html Mac/Linux 使用脚本进行安装或更新 curl -o- …...

uni-appx使用form表单页面初始化报错

因为UniFormSubmitEvent的类型时 e-->detail-->value,然后没有了具体值。所以页面初始化的时候 不能直接从value取值&#xff0c;会报错找不到 所以form表单里的数据我们要设置成一个对象来存放 这个问题的关键在于第22行代码 取值&#xff1a; 不能按照点的方式取值 …...

TiDB-从0到1-数据导出导入

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇TiDB-从0到1-集群扩缩容 一、数据导出 TiDB中通过Dumpling来实现数据导出&#xff0c;与MySQL中的mysqldump类似&#xff0c;其属于…...

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-16自定义层

16自定义层 import torch import torch.nn.functional as F from torch import nnclass CenteredLayer(nn.Module):def __init__(self):super().__init__()#从其输入中减去均值#X.mean() 计算的是整个张量的均值#希望计算特定维度上的均值&#xff0c;可以传递 dim 参数。#例如…...

树莓派4设置

使用sudo命令时要求输入密码 以 sudo 为前缀的命令以超级用户身份运行。默认情况下&#xff0c;超级用户不需要密码。不过&#xff0c;您可以要求所有以 sudo 运行的命令都输入密码&#xff0c;从而提高 Raspberry Pi 的安全性。 要强制 sudo 要求输入密码&#xff0c;请为你…...

44.商城系统(二十五):k8s基本操作,ingress域名访问,kubeSphere可视化安装

上一章我们已经配置好了k8s集群,如果没有配置好先去照着上面的配。 一、k8s入门操作 1.部署一个tomcat,测试容灾恢复 #在主机器上执行 kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8#查看k8s中的所有资源 kubectl get all kubectl get all -o wide#查看po…...

MySQL高级查询

MySQL 前言 文本源自微博客 (www.microblog.store),且已获授权. 一. mysql基础知识 1. mysql常用系统命令 启动命令 net start mysql停止命令 net stop mysql登录命令 mysql -h ip -P 端口 -u 用户名 -p ​ 本机可以省略 ip mysql -u 用户名 -p 查看数据库版本 mysql --ve…...

聊聊啥项目适合做自动化测试

作为测试从业者&#xff0c;你是否遇到过这样的场景&#xff0c;某天公司大Boss找你谈话。 老板&#xff1a;小李&#xff0c;最近工作辛苦了 小李&#xff1a;常感谢您的认可&#xff0c;这不仅是对我个人的鼓励&#xff0c;更是对我们整个团队努力的认可。我们的成果离不开每…...

ROS2开发机器人移动

.创建功能包和节点 这里我们设计两个节点 example_interfaces_robot_01&#xff0c;机器人节点&#xff0c;对外提供控制机器人移动服务并发布机器人的状态。 example_interfaces_control_01&#xff0c;控制节点&#xff0c;发送机器人移动请求&#xff0c;订阅机器人状态话题…...

【强化学习】第02期:动态规划方法

笔者近期上了国科大周晓飞老师《强化学习及其应用》课程&#xff0c;计划整理一个强化学习系列笔记。笔记中所引用的内容部分出自周老师的课程PPT。笔记中如有不到之处&#xff0c;敬请批评指正。 文章目录 2.1 动态规划&#xff1a;策略收敛法/策略迭代法2.2 动态规划&#xf…...

安全技术和防火墙(二)

接上一节 备份和还原 iptables-save > /opt/iptables.bak iptables-restore < /opt/iptables.bak snat和dnat snat源地址转换 内网到外网 内网ip转换成可以访问外网的ip 内网的多个主机可以只有一个有效的公网ip地址访问外部网络 dnat 目的地址转发 外部用户&#…...

【51单片机入门】数码管原理

文章目录 前言共阴极与共阳极数码管多个数码管显示原理 总结 前言 在我们的日常生活中&#xff0c;数码管被广泛应用于各种电子设备中&#xff0c;如电子表、计时器、电子钟等。数码管的主要功能是显示数字和一些特殊字符。在这篇文章中&#xff0c;我们将探讨数码管的工作原理…...

三星DRAM、NAND,“又双叒叕”带头涨价了

据韩国媒体《每日经济新闻》报道&#xff0c;三星电子计划在第三季度上调服务器DRAM和企业级NAND闪存的价格&#xff0c;涨幅预计在15%-20%&#xff0c;主要受人工智能(AI)需求激增的推动。这一举措有望提振公司下半年业绩。 据《经济日报》报道援引业内消息&#xff0c;由于厂…...

vue组件深入介绍之插槽

了解插槽之前请先了解vue组件基础及注册 Vue2官网介绍 Vue3官网介绍 1、vue2插槽介绍 在2.6.0中&#xff0c;具名插槽和作用域插槽引入了一个新的统一语法&#xff08;v-slot指令&#xff09;。它将取代slot和slot-scope&#xff1b; Vue 实现了一套内容分发的 API&#xf…...

Docker部署ETCD 3.5.14(保姆级图文教程)

系列文章目录 Docker部署Nginx 1.21.5&#xff08;保姆级图文教程&#xff09; Docker部署MySQL 8.3.0&#xff08;保姆级图文教程&#xff09; Docker部署ETCD 3.5.14&#xff08;保姆级图文教程&#xff09; 文章目录 一、环境二、拉取镜像2.1 查找 Docker Hub 上的 ETCD 镜像…...

hexo博客搭建

系列文章目录 文章目录 系列文章目录前言1. 环境配置2. 打包并发布到github仓库3. 生成ssh秘钥4.vscode配置本地与远端相对路径不一致问题总结 前言 本文主要介绍了hexo博客怎么搭建 1. 环境配置 安装git、nodejs、npm创建博客文件夹blogcmd输入命令npm install -g hexo初始化…...

机器学习 C++ 的opencv实现SVM图像二分类的训练 (二)【附源码】

本节讲机器学习 C 的opencv实现SVM图像二分类的训练&#xff0c;下节讲测试&#xff1a; 数据集合data内容如下&#xff1a; 下载地址为&#xff1a;https://download.csdn.net/download/hgaohr1021/89506900 #include <stdio.h> #include <time.h> #include…...

【海思Hi3403V100】多目拼接相机套板硬件规划方案

海思Hi3403V100 是专业超高清智能网络摄像头 SoC。该芯片最高支持四路 sensor 输入&#xff0c;支持最高 4K60fps 的 ISP 图像处理能力&#xff0c;支持 3F 、WDR、多级降噪、六轴防抖、硬件拼接、多光谱融合等多种传统图像增强和处理算法&#xff0c;支持通过AI 算法对输入图像…...

【Verilog HDL-1】基本、向量、模块

HDL习题 1 阻塞型赋值‘’与非阻塞型赋值‘<’ 阻塞型赋值 b a ba ba&#xff1a;适用于纯组合电路 非阻塞型赋值 b < a b<a b<a&#xff1a;适用与时序逻辑电路 2 wire线型,assign连续赋值 wire a,b,c; assign b a; assign c a;与编程语言不同&#xff…...

20万级技术点满智己L6真不错但更多人会选“34C”

智己L6上市了,权益价19.99万元起步,这个价格标配激光雷达、英伟达的芯片、四轮转向、8295P,就不只是卷了,甚至可能是在赔本卖车。看起来没有不买它的理由了,但事实情况是,大部分人会选择再加5万,买传统豪华品牌。智己L6是真不错在智己公布预售价的时候,我们认为它应该还…...

人工智能初识

&#x1f31e;欢迎来到人工智能基础的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年5月1…...

C#压缩单个文件

1、压缩方法 /// <summary> /// 压缩 /// </summary> /// <param name"source">源目录</param> /// <param name"s">ZipOutputStream对象</param> public static void Compress(string source, ZipOutputStream s) {…...

Django入门全攻略:从零搭建你的第一个Web项目

系列文章目录 努力ing Django入门全攻略&#xff1a;从零搭建你的第一个Web项目努力ing… 文章目录 系列文章目录前言一、Django1.1 Django安装1.2 Django项目创建1.3 目录介绍 二、子应用2.1 子应用创建2.2 目录结构2.3 子应用注册2.4 子应用视图逻辑2.4.1 编写视图2.4.2 编写…...

Matlab|基于PMU相量测量单元进行电力系统电压幅值和相角状态估计

主要内容 程序采用三种方法对14节点和30节点电力系统状态进行评估&#xff1a; ①PMU同步相量测量单元结合加权最小二乘法&#xff08;WLS&#xff09;分析电力系统的电压幅值和相角状态&#xff1b; ②并采用牛顿-拉夫逊方法进行系统潮流计算&#xff0c;结果作为理论分…...

【CSharp】判断目录以及文件是否存在

【CSharp】判断目录以及文件是否存在 1.背景2.判断目录3.判断文件1.背景 我们在进行磁盘IO的时候进行需要判断目录、文件是否存在,根据判断结果再做进一步的操作。 其中判断目录是否存在,涉及Directory.Exists(String) 方法; 命名空间:System.IO 方法功能:确定给定路径是…...