税务局电子发票接口api

更新时间: 2024.11.21 06:39 阅读:

用一系列文章介绍如何用python写一个发票管理小工具。

本文介绍如何用Uvicorn+FastAPI搭建后台接口,如何使用loguru打印日志,以及自动打开浏览器显示前端页面。

税务局电子发票接口api(图1)

代码结构

基本思路

大家一般运行Uvicorn都是uvicorn.run()直接运行,这样uvicorn启动后会阻塞程序,后续无法执行代码。

所以这里我们使用Python多进程,一个主进程用于打开浏览器以及后续其他功能,一个独立的子进程运行Uvicorn。

配置文件

创建一个配置文件config.yml,编写config.py用于读取配置文件。使用ruamel.yaml模块读取yaml文件。

#config.pyfrom ruamel.yaml import YAMLclass AppConfig():def __init__(self):with open("config/config.yml","r",encoding="utf-8") as configFile:yaml = YAML()conf = yaml.load(configFile)self.config = confself.loguru = self.config['loguru']self.uvicorn = self.config['uvicorn']appConfig = AppConfig()
# config.yml# 日志配置loguru:format: '{time:YYYY-MM-DDTHH:mm:ss.SSSZ} {level} tid[{extra[tid]}] {message}'level: DEBUGfile: logs/application.logrotation: 00:00retention: 30 days# uvicorn设置uvicorn:host: 127.0.0.1port: 8088# 等待web服务启动时间,服务启动后自动打开浏览器waitWebServerTime: 10

独立进程运行Uvicorn

使用multiprocessing.Process创建子进程,注意设置daemon=True,这样主进程关闭时会自动关掉子进程。

import uvicornfrom multiprocessing import Processfrom config import appConfigdef runUvicorn():uvicorn.run("webapi:app", host=appConfig.uvicorn["host"], port=appConfig.uvicorn["port"], reload=False, log_config='config/uvicornLog.json', access_log=True, workers=1)# 启动web服务webapiProcess = Process(target=runUvicorn, name="webapi_process", daemon=True)webapiProcess.start()try:while True:time.sleep(1)except KeyboardInterrupt: logger.info("user interrupt, close application")sys.exit(0)

日志增加TID

为了方便日志追踪,一般我们都会在日志中打印一个transaction_id,用户一个请求过程中的所有日志都有这样一个唯一的transaction_id。

我们使用loguru模块来打印日志,loguru配置和使用非常简单,而且我们的程序使用了多进程,loguru是支持多进程的。

第一节的配置文件中已经有loguru需要的配置项了,下面介绍如何使用loguru,以及fastapi如何生成transaction_id,并且将tid添加到日志中。

创建log.py

from loguru import loggerimport sysfrom config import appConfiglogger.remove()logger.configure(extra={"tid":""})logger.add(sys.stderr,enqueue=True, format=appConfig.loguru["format"], level=appConfig.loguru["level"])logger.add(appConfig.loguru["file"], enqueue=True, format=appConfig.loguru["format"], level=appConfig.loguru["level"], rotation=appConfig.loguru["rotation"], retention=appConfig.loguru["retention"])

需要关注的是logger.configure(extra={"tid":""})这一行,将tid添加到日志record的extra中,extra是loguru提供给用户添加自定义日志字段的属性。虽然也有办法直接修改record,但是建议添加到extra中。

在webapi.py中添加middleware,在收到请求时生成tid。然后通过loguru的pach将tid添加到日志record中。

#webapi.pyfrom random import randintfrom typing import Callable, Optionalfrom fastapi import FastAPI,Requestfrom loguru import loggerfrom datetime import datetimefrom contextvars import ContextVar# 用于日志记录当前请求IDtransaction_id: ContextVar[Optional[str]] = ContextVar('transaction_id', default='')def transaction_id_filter(record):record['extra']['tid'] = transaction_id.get()return record# 此处向日志中设置tidlogger.configure(patcher=transaction_id_filter)app = FastAPI(title='My Invoice Folder', docs_url=None, redoc_url=None)# 生成请求ID@app.middleware("http")async def create_transaction_id(request: Request, call_next: Callable):# tid格式为时间戳+4位随机数transaction_id.set(f"{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}{randint(1000, 9999)}")response = await call_next(request)return response

将fastapi首页设置为发票夹页面

我们之前已经写了一个发票夹html页面,这里直接将fastapi首页跳转到这个页面就可以了。

将页面资源都放到项目ui文件夹中,加载ui文件夹。

app.mount("/ui", StaticFiles(directory="ui"), name="ui")

设置首页跳转

# 首页跳转到我的发票夹页面@app.get("/", include_in_schema=False)def read_root():logger.info("access index page")return RedirectResponse("/ui/index.html")

自动打开浏览器显示发票夹页面

首先我们在启动Uvicorn进程后,使用request请求首页,如果请求成功,则打开系统默认浏览器并打开发票夹首页。代码如下:

# 启动系统默认浏览器打开界面waitWebServerTime = appConfig.config["waitWebServerTime"]openBrowserSuccess = Falsewhile waitWebServerTime > 0:time.sleep(1)try: # 判断web服务是否已启动indexUrl = f'http://{appConfig.uvicorn["host"]}:{appConfig.uvicorn["port"]}/'response = requests.get(indexUrl, timeout=1)if response.status_code == 200:# 打开主页openBrowserSuccess = openBrowser(indexUrl)breakexcept Exception as e:passwaitWebServerTime -= 1

总结

现在我们可以直接运行main.py,就可以运行后端api,并且自动打开浏览器看到页面了~后续逻辑抽空继续写。

税务局电子发票接口api(图2)

控制台日志

税务局电子发票接口api(图3)

自动打开浏览器,访问本地页面

代码比较多,已经上传到github(https://github.com/xy12358/my-invoice-folder.git)和gitee(https://gitee.com/xinying/my-invoice-folder)。

•••展开全文
标签: 暂无
没解决问题?查阅“相关文档”