diff --git a/app.py b/app.py index a692fae..0c4ae84 100644 --- a/app.py +++ b/app.py @@ -3,9 +3,11 @@ # LastEditors: 宁静致远 468835121@qq.com # LastEditTime: 2024-02-16 22:15:25 +""" +这里做一下重写, +""" + import fastapi -import os -import importlib import logging from config import settings @@ -18,25 +20,5 @@ # include services -services_path='services' -if not os.path.exists(services_path): - logger.critical(f"{os.path.join(os.getcwd(),services_path)} 不存在") - raise - -services = os.listdir(services_path) -for service in services: - try: - entrypoint = importlib.import_module(f"{services_path}.{service}").entrypoint - matedata = entrypoint(settings) - logger.warn("#"*50+f""" -加载{service} -\t作者{matedata['Author']} -\t版本{matedata['Version']} -\t描述{matedata['Describe']} -"""+"#"*50) - application.include_router(matedata['Router']) - matedata['Init']() - except Exception as e: - logger.warn(f"加载{service}出错") - logger.warn(e) - if settings.get('debug',default=False):raise e +from services import createAPIRouter +application.include_router(createAPIRouter()) \ No newline at end of file diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..cd98d7f --- /dev/null +++ b/services/__init__.py @@ -0,0 +1,12 @@ +''' +Date: 2024-02-18 15:57:15 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 15:59:59 +''' +def createAPIRouter(): + from fastapi import APIRouter + router = APIRouter() + from . import example_service2,example_service3 + router.include_router(example_service2.createAPIRouter()) + router.include_router(example_service3.createAPIRouter()) + return router \ No newline at end of file diff --git a/services/example-service1/__init__.py b/services/example-service1/__init__.py deleted file mode 100644 index 1b8d08a..0000000 --- a/services/example-service1/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -''' -Date: 2024-02-16 13:29:36 -LastEditors: 宁静致远 468835121@qq.com -LastEditTime: 2024-02-16 22:44:57 -''' -# -*- coding: utf-8 -*- -# Date: 2024-02-16 13:29:36 -# LastEditors: 宁静致远 468835121@qq.com -# LastEditTime: 2024-02-16 22:15:40 - -from fastapi import APIRouter -from dynaconf import Dynaconf - -router = APIRouter(prefix="/njzy") - -def entrypoint(settings:Dynaconf): - ''' - description: 这个是入口点,会传入一个settings - return { - "Author":作者, - "Version":版本号, - "Describe":描述, - "Router":路由对象在这里, - "Init":载入路由之后的初始(可以放其他线程启动啥的,别阻塞), -} - ''' - return { - "Author":"宁静致远", - "Version":'1.0.0', - "Describe":""" -实例微服务,主要测试能不能用 -""", - "Router":router, - "Init":lambda:init(settings), -} - -g_settings=None - -def init(a:Dynaconf): - print('原神~启动!') - print(f'试着读配置{a.get("test")}') - global g_settings - g_settings=a - -@router.get("/") -def index(): - return {"success":True,"settings":g_settings} \ No newline at end of file diff --git a/services/example_service1/__init__.py b/services/example_service1/__init__.py new file mode 100644 index 0000000..874c5c0 --- /dev/null +++ b/services/example_service1/__init__.py @@ -0,0 +1,22 @@ +""" +每一个模块必须的文件: + - __init__.py + - router.py + - api.py + + +__init__.py必须提供的东西: + - entrypoint(settings: dict) -> dict + - init_router(settings: dict) -> fastapi.APIRouter +""" +from . import router +from . import api + +def entrypoint(settings: dict): + return { + "Author": "Example ", + "Version": "0.0.1", + "Description": "Example Service 1", + "PublicRouter": router.router, + "API": api, + } diff --git a/services/example_service1/api.py b/services/example_service1/api.py new file mode 100644 index 0000000..b4c1bae --- /dev/null +++ b/services/example_service1/api.py @@ -0,0 +1,19 @@ +""" +这个文件是必须的。 + +这个文件定义了对模块提供的API。 + +提供方式 **只能** 是对业务逻辑的 import, 不能进行其他处理。 + +---------------------------------------------- +别的模块通过 + +```py +from services.example_service1.api imoprt API1, API2, ... +``` + +来使用这个模块提供的API。 +这些对模块暴露的api在这里被定义。 +""" + +from .func import add, hlwd diff --git a/services/example_service1/func.py b/services/example_service1/func.py new file mode 100644 index 0000000..d77edc3 --- /dev/null +++ b/services/example_service1/func.py @@ -0,0 +1,29 @@ +""" +这里是功能文件, 也就是该service内部的业务逻辑, 不管你怎么写, 分成不同的文件也可以。 +""" + +def plus(a, b): + """ + [tools] plus a and b + """ + return a + b + + +def add(a, b): + """ + add a and b + + :param a: int + :param b: int + + :return: int + """ + return plus(a, b) + +def hlwd(): + """ + say hello world + + :return: str + """ + return "Hello World!" diff --git a/services/example_service1/router.py b/services/example_service1/router.py new file mode 100644 index 0000000..adac8c9 --- /dev/null +++ b/services/example_service1/router.py @@ -0,0 +1,103 @@ +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 15:51:41 +''' +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 15:44:36 +''' +""" +[该文件为必须文件] +router.py用于定义对外公开的api路由, 并提供一个router对象供__init__.py调用。 + +需要提供的东西: + - router: fastapi.APIRouter + +---------------------------------------------------------- +这里的函数应当能直接处理fastapi的调用。 + +一般该函数的内容: +1. Get Parameter 从http请求中取获取参数 +2. Type Check 进行类型校验 +3. Type Convert 进行类型转化 +4. Process 调用api.py内的api函数。(提供给外部的api显然也得提供给内部) +5. Return 处理业务函数的返回值, reformat为json或其他格式, 返回给用户。 + +【注意】:为了保证代码简洁,这里的函数 **只能** 调用提供给业务逻辑函数。 +""" + +import fastapi + +from . import api + + +router = fastapi.APIRouter(prefix="/example") + +@router.get("/add") +def add(a:int,b:int): + """ + 对func.add进行简单封装。 + + 从参数中获取a和b, 做类型转化, 然后调用api.add。 + **(为了代码整齐, 只能做这些)** + + :param a: int + :param b: int + + :return: int + """ + # Get parameter + # request = fastapi.Request() + # a = request.args.get("a") + # b = request.args.get("b") + + # Type Check + if not isinstance(a, int) or not isinstance(b, int): + return { + "code": 1, + "msg": "Parameter Error", + "data": None + } + + # Type Convert + a = int(a) + b = int(b) + + # Process + ret = api.add(a, b) + + # Return + return { + "code": 0, + "msg": "Success", + "data": ret + } + +@router.get("/wrong") +def wrong_example(a:int,b:int,c:int): + """ + 一个 **错误** 的例子。 + + 这个函数调用了两个业务逻辑函数, 这是不允许的。 + + :return: int + """ + # Get parameter + # request = fastapi.Request() + # a = request.args.get("a") + # b = request.args.get("b") + # c = request.args.get("c") + + # [Warning!] Call two business logic function + ret = api.add(a, b) + api.add(b, c) + # or + ret = api.add(api.add(a, b), c) + + # Return + return { + "code": 0, + "msg": "Success", + "data": ret + } diff --git a/services/example_service2/__init__.py b/services/example_service2/__init__.py new file mode 100644 index 0000000..0db927b --- /dev/null +++ b/services/example_service2/__init__.py @@ -0,0 +1,9 @@ +''' +Date: 2024-02-18 15:54:04 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 16:02:04 +''' + +def createAPIRouter(): + from . import router + return router.router \ No newline at end of file diff --git a/services/example_service2/api.py b/services/example_service2/api.py new file mode 100644 index 0000000..97af9b3 --- /dev/null +++ b/services/example_service2/api.py @@ -0,0 +1,25 @@ +''' +Date: 2024-02-18 15:54:04 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 16:02:42 +''' +""" +这个文件是必须的。 + +这个文件定义了对模块提供的API。 + +提供方式 **只能** 是对业务逻辑的 import, 不能进行其他处理。 + +---------------------------------------------- +别的模块通过 + +```py +from services.example_service1.api imoprt API1, API2, ... +``` + +来使用这个模块提供的API。 +这些对模块暴露的api在这里被定义。 +""" + +def me(a): + return f"I'm e2. say {a}" \ No newline at end of file diff --git a/services/example_service2/router.py b/services/example_service2/router.py new file mode 100644 index 0000000..1809449 --- /dev/null +++ b/services/example_service2/router.py @@ -0,0 +1,65 @@ +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 16:10:16 +''' +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 15:44:36 +''' +""" +[该文件为必须文件] +router.py用于定义对外公开的api路由, 并提供一个router对象供__init__.py调用。 + +需要提供的东西: + - router: fastapi.APIRouter + +---------------------------------------------------------- +这里的函数应当能直接处理fastapi的调用。 + +一般该函数的内容: +1. Get Parameter 从http请求中取获取参数 +2. Type Check 进行类型校验 +3. Type Convert 进行类型转化 +4. Process 调用api.py内的api函数。(提供给外部的api显然也得提供给内部) +5. Return 处理业务函数的返回值, reformat为json或其他格式, 返回给用户。 + +【注意】:为了保证代码简洁,这里的函数 **只能** 调用提供给业务逻辑函数。 +""" + +import fastapi + +from . import api + + +router = fastapi.APIRouter(prefix="/example2") + +@router.get("/add") +def add(a:int,b:int): + """ + 对func.add进行简单封装。 + + 从参数中获取a和b, 做类型转化, 然后调用api.add。 + **(为了代码整齐, 只能做这些)** + + :param a: int + :param b: int + + :return: int + """ + # Get parameter + # request = fastapi.Request() + # a = request.args.get("a") + # b = request.args.get("b") + + + # Process + ret = a + b + + # Return + return { + "code": 0, + "msg": "Success", + "data": ret + } diff --git a/services/example_service3/__init__.py b/services/example_service3/__init__.py new file mode 100644 index 0000000..75b741d --- /dev/null +++ b/services/example_service3/__init__.py @@ -0,0 +1,4 @@ + +def createAPIRouter(): + from . import router + return router.router diff --git a/services/example_service3/api.py b/services/example_service3/api.py new file mode 100644 index 0000000..d48a19b --- /dev/null +++ b/services/example_service3/api.py @@ -0,0 +1,18 @@ +""" +这个文件是必须的。 + +这个文件定义了对模块提供的API。 + +提供方式 **只能** 是对业务逻辑的 import, 不能进行其他处理。 + +---------------------------------------------- +别的模块通过 + +```py +from services.example_service1.api imoprt API1, API2, ... +``` + +来使用这个模块提供的API。 +这些对模块暴露的api在这里被定义。 +""" + diff --git a/services/example_service3/router.py b/services/example_service3/router.py new file mode 100644 index 0000000..cab76f7 --- /dev/null +++ b/services/example_service3/router.py @@ -0,0 +1,43 @@ +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 16:10:28 +''' +''' +Date: 2024-02-18 15:41:17 +LastEditors: 宁静致远 468835121@qq.com +LastEditTime: 2024-02-18 15:44:36 +''' +""" +[该文件为必须文件] +router.py用于定义对外公开的api路由, 并提供一个router对象供__init__.py调用。 + +需要提供的东西: + - router: fastapi.APIRouter + +---------------------------------------------------------- +这里的函数应当能直接处理fastapi的调用。 + +一般该函数的内容: +1. Get Parameter 从http请求中取获取参数 +2. Type Check 进行类型校验 +3. Type Convert 进行类型转化 +4. Process 调用api.py内的api函数。(提供给外部的api显然也得提供给内部) +5. Return 处理业务函数的返回值, reformat为json或其他格式, 返回给用户。 + +【注意】:为了保证代码简洁,这里的函数 **只能** 调用提供给业务逻辑函数。 +""" + +import fastapi + +from . import api + +# 模块间调用 +from ..example_service2.api import me + + +router = fastapi.APIRouter(prefix="/example3") + +@router.get("/say") +def say(a:str): + return me(a)