我正在构建一个快速API服务器,代表我的客户提供代码。
所以我的目录结构是:
project
| main.py
|--customer_code (mounted at runtime)
| blah.py
在main.py
中我有:
from customer_code import blah
from fastapi import FastAPI
app = FastAPI()
...
@app.post("/do_something")
def bar(# I want this to have the same type as blah.foo()):
blah.foo()
在blah.py
中我有:
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'John Doe'
def foo(data : User):
# does something
我不知道我的客户的代码(在blah.py
中)会是什么类型。但我想使用FastAPI内置的OpenAPI模式生成(而不是要求我的客户接受和解析JSON输入)。
有没有办法将要栏
的参数类型设置为与要 foo
的参数类型相同?
似乎有一种方法是用花哨的字符串插值来执行exec
,但我担心这不是真正的Pythonic,我还必须清理用户的输入。所以如果有另一个选择,很想学习。
首先考虑装饰者的定义。来自Python Decorators入门:
装饰器是一个函数,它接受另一个函数并扩展后一个函数的行为而不显式修改它
app.post(“/do_something”)
返回一个装饰器,该装饰器接收示例中的 def bar(...)
函数。关于@
的用法,前面提到的同一页面说:
@my_decorator只是更简单的表示方式 say_whee = my_decorator(say_whee)
所以你可以用这样的话:
app.post("/do_something")(blah.foo)
而blah
的foo
函数将由FastAPI公开。除非您还想在调用foo
之前或在返回foo<-code>之后执行一些操作,否则它可能会结束。如果是这种情况,你需要有自己的装饰师。
完整示例:
# main.py
import functools
import importlib
from typing import Any
from fastapi import FastAPI
app = FastAPI()
# Create your own decorator if you need to intercept the request/response
def decorator(func):
# Use functools.wraps() so that the returned function "look like"
# the wrapped function
@functools.wraps(func)
def wrapper_decorator(*args: Any, **kwargs: Any) -> Any:
# Do something before if needed
print("Before")
value = func(*args, **kwargs)
# Do something after if needed
print("After")
return value
return wrapper_decorator
# Import your customer's code
blah = importlib.import_module("customer_code.blah")
# Decorate it with your decorator and then pass it to FastAPI
app.post("/do_something")(decorator(blah.foo))
# customer_code.blah.py
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'John Doe'
def foo(data: User) -> User:
return data
最后使用了以下答案:
from fastapi import Depends, FastAPI
from inspect import signature
from pydantic import BaseModel, create_model
sig = signature(blah.foo)
query_params = {}
for k in sig.parameters:
query_params[k] = (sig.parameters[k].annotation, ...)
query_model = create_model("Query", **query_params)
所以这个函数看起来像这样:
@app.post("/do_something")
def bar(params: query_model = Depends()):
p_as_dict = params.as_dict()
return blah.foo(**p_as_dict)
这回答了你的问题吗?
def f1(a: str, b: int):
print('F1:', a, b)
def f2(c: float):
print('F2:', c)
def function_with_unknown_arguments_for_f1(*args, **kwargs):
f1(*args, **kwargs)
def function_with_unknown_arguments_for_f2(*args, **kwargs):
f2(*args, **kwargs)
def function_with_unknown_arguments_for_any_function(func_to_run, *args, **kwargs):
func_to_run(*args, **kwargs)
function_with_unknown_arguments_for_f1("a", 1)
function_with_unknown_arguments_for_f2(1.1)
function_with_unknown_arguments_for_any_function(f1, "b", 2)
function_with_unknown_arguments_for_any_function(f2, 2.2)
输出:
F1: a 1
F2: 1.1
F1: b 2
F2: 2.2
这是关于参数
和夸格的
详细说明
换句话说,后
函数应该像
@app.post("/do_something")
def bar(*args, **kwargs):
blah.foo(*args, **kwargs)
为了能够处理动态变化的foo
关于OpenAPI
:
非常确定可以覆盖文档生成器类或函数,并根据foo
而不是特定视图的bar
设置有效负载类型。
以下是如何扩展OpenAPI的几个示例。它与您的问题没有直接关系,但可能有助于理解它是如何工作的。
我想这样设置参数的类型: 当我尝试这样做时,会引发错误:NameError:名称'Tree'未定义
我的问题与新Python的类型提示有关。我试图在对象的方法中添加一个类型提示,它具有与对象相同类型的参数,但PyCharm将我标记为错误()。问题如下: 因此,问题是如何正确定义参数的类型。也许是正确的?
函数 要声明一个函数,需要使用关键字fn,后面跟上函数名,比如 fn add_one(x: i32) -> i32 { x + 1 } 其中函数参数的类型不能省略,可以有多个参数,但是最多只能返回一个值, 提前返回使用return关键字。Rust编译器会对未使用的函数提出警告, 可以使用属性#[allow(dead_code)]禁用无效代码检查。 Rust有一个特殊特性适用于发散函数 (d
我想使返回数据类型的的函数与传入的参数的数据类型相同。例如,我会这样调用函数: 因为我将一个传递给,所以它返回了一个
问题内容: 我已经看到了一些类似的问题两种不同的类型如何使用接口在golang中实现相同的方法?,但就我而言,我的类型没有相同的基本类型。我的类型是不同大小的数组。 因此,可能不重复两种方法GetByte0()? 问题答案: 例如, 输出:
我在Java中有两个几乎相同的方法。唯一的区别是它们有不同的参数类型。它们使用泛型并返回输入参数的类型T。我怎样才能摆脱重复的代码?下面是我的两个方法。最后,它们都使用不同的类型调用Spring。否则,方法是相同的。