原来的官方方式要自己import,然后注册到路由列表里面。感觉麻烦,有没有我自己写好controller层,自己注册路由呢。后面研究下,发现可以。
1.在system.py里面写类似这个代码
def initRouter(app: FastAPI):
for root, dirs, files in os.walk(os.path.join(os.getcwd(), "router")):
for file in files:
if file.find("__init__") > -1 or file.find(".pyc") > -1:
continue
file = file.replace(".py", "")
m = importlib.import_module('router.'+file)
app.include_router(m.router)
class Init:
@staticmethod
def do(app: FastAPI):
initRouter(app)
原理就是获取在router文件夹下面的文件然后导入模块自己注册到路由
如果有需要打包为exe文件用
def initRouter(app: FastAPI):
# 解析规则:放在router模块下面的文件 (文件夹下文件)
# 是否为已打包环境
if getattr(sys, "frozen", False):
base_path = os.path.join(sys._MEIPASS, "router")
else:
base_path = os.path.join(os.getcwd(), "router")
# 获取当前目录下所有非目录项(即文件)
files_in_current_dir = [
f
for f in os.listdir(base_path)
if os.path.isfile(os.path.join(base_path, f))
]
for file in files_in_current_dir:
file = file.replace(".py", "")
if file in ["__init__", ".pyc"]:
continue
module = importlib.import_module("router." + file)
if hasattr(module, "router"):
app.include_router(module.router)
2.调用初始化路由
from util.system import Init
app = FastAPI()
Init.do(app)
if __name__ == '__main__':
uvicorn.run('main:app', host='0.0.0.0', port=8000, reload=True, workers=1)
上面第一步是简单版本得。局限是不能多层级嵌套,只能放在某个文件夹下顶级的文件。适合做点简单的测试原型,或微小项目
优化版本如下,支持在不同文件夹下。一个文件夹是一个模块。比较适合业务比较多的时候
def initRouter(app: FastAPI):
# 解析规则:server模块下面的带controller字符的文件 (文件夹下特定文件)
for path in Path(os.getcwd() + "/server").rglob("*.py"):
# 使用pathlib更方便地遍历文件
if "controller" in path.name.lower():
module_name = path.stem # 不包含扩展名的文件名
try:
# 动态导入模块
full_module_name = f"server.{path.parent.name}.{module_name}"
module = importlib.import_module(full_module_name)
# 添加路由
if hasattr(module, "router"):
app.include_router(module.router)
except Exception as e:
print(f"导入模块失败: {full_module_name} : {e}")
简单版本 github.com/MrYZhou/cod… 优化版本 github.com/MrYZhou/lga…
总结:动态注册配合热更新,我再也不用手动关心怎么注册到应用。最后我觉得python框架这块应该自己写个装饰器给我们用才对。就像boot那样@Controller自动注入。这点肯定可以实现的。最后希望大家能喜欢我的分享。