国产东北多p真实在线_惠民福利日韩爽到高潮的免费视频_bt天堂在线观看www_小草色网视频免费播放_日日AAV视频网站免费看_亚洲欧美人精品高清_人妻无码久久精品人妻_精品无码免费在线_一区二区日韩动漫av_国产欧美另类第一页

稅務(wù)局電子發(fā)票接口api

更新時(shí)間: 2024.11.24 03:28 閱讀:

用一系列文章介紹如何用python寫一個(gè)發(fā)票管理小工具。

本文介紹如何用Uvicorn+FastAPI搭建后臺(tái)接口,如何使用loguru打印日志,以及自動(dòng)打開瀏覽器顯示前端頁(yè)面。

稅務(wù)局電子發(fā)票接口api(圖1)

代碼結(jié)構(gòu)

基本思路

大家一般運(yùn)行Uvicorn都是uvicorn.run()直接運(yùn)行,這樣uvicorn啟動(dòng)后會(huì)阻塞程序,后續(xù)無(wú)法執(zhí)行代碼。

所以這里我們使用Python多進(jìn)程,一個(gè)主進(jìn)程用于打開瀏覽器以及后續(xù)其他功能,一個(gè)獨(dú)立的子進(jìn)程運(yùn)行Uvicorn。

配置文件

創(chuàng)建一個(gè)配置文件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設(shè)置uvicorn:host: 127.0.0.1port: 8088# 等待web服務(wù)啟動(dòng)時(shí)間,服務(wù)啟動(dòng)后自動(dòng)打開瀏覽器waitWebServerTime: 10

獨(dú)立進(jìn)程運(yùn)行Uvicorn

使用multiprocessing.Process創(chuàng)建子進(jìn)程,注意設(shè)置daemon=True,這樣主進(jìn)程關(guān)閉時(shí)會(huì)自動(dòng)關(guān)掉子進(jìn)程。

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)# 啟動(dòng)web服務(wù)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

為了方便日志追蹤,一般我們都會(huì)在日志中打印一個(gè)transaction_id,用戶一個(gè)請(qǐng)求過(guò)程中的所有日志都有這樣一個(gè)唯一的transaction_id。

我們使用loguru模塊來(lái)打印日志,loguru配置和使用非常簡(jiǎn)單,而且我們的程序使用了多進(jìn)程,loguru是支持多進(jìn)程的。

第一節(jié)的配置文件中已經(jīng)有l(wèi)oguru需要的配置項(xiàng)了,下面介紹如何使用loguru,以及fastapi如何生成transaction_id,并且將tid添加到日志中。

創(chuàng)建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"])

需要關(guān)注的是logger.configure(extra={"tid":""})這一行,將tid添加到日志record的extra中,extra是loguru提供給用戶添加自定義日志字段的屬性。雖然也有辦法直接修改record,但是建議添加到extra中。

在webapi.py中添加middleware,在收到請(qǐng)求時(shí)生成tid。然后通過(guò)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# 用于日志記錄當(dāng)前請(qǐng)求IDtransaction_id: ContextVar[Optional[str]] = ContextVar('transaction_id', default='')def transaction_id_filter(record):record['extra']['tid'] = transaction_id.get()return record# 此處向日志中設(shè)置tidlogger.configure(patcher=transaction_id_filter)app = FastAPI(title='My Invoice Folder', docs_url=None, redoc_url=None)# 生成請(qǐng)求ID@app.middleware("http")async def create_transaction_id(request: Request, call_next: Callable):# tid格式為時(shí)間戳+4位隨機(jī)數(shù)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首頁(yè)設(shè)置為發(fā)票夾頁(yè)面

我們之前已經(jīng)寫了一個(gè)發(fā)票夾html頁(yè)面,這里直接將fastapi首頁(yè)跳轉(zhuǎn)到這個(gè)頁(yè)面就可以了。

將頁(yè)面資源都放到項(xiàng)目ui文件夾中,加載ui文件夾。

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

設(shè)置首頁(yè)跳轉(zhuǎn)

# 首頁(yè)跳轉(zhuǎn)到我的發(fā)票夾頁(yè)面@app.get("/", include_in_schema=False)def read_root():logger.info("access index page")return RedirectResponse("/ui/index.html")

自動(dòng)打開瀏覽器顯示發(fā)票夾頁(yè)面

首先我們?cè)趩?dòng)Uvicorn進(jìn)程后,使用request請(qǐng)求首頁(yè),如果請(qǐng)求成功,則打開系統(tǒng)默認(rèn)瀏覽器并打開發(fā)票夾首頁(yè)。代碼如下:

# 啟動(dòng)系統(tǒng)默認(rèn)瀏覽器打開界面waitWebServerTime = appConfig.config["waitWebServerTime"]openBrowserSuccess = Falsewhile waitWebServerTime > 0:time.sleep(1)try: # 判斷web服務(wù)是否已啟動(dòng)indexUrl = f'http://{appConfig.uvicorn["host"]}:{appConfig.uvicorn["port"]}/'response = requests.get(indexUrl, timeout=1)if response.status_code == 200:# 打開主頁(yè)openBrowserSuccess = openBrowser(indexUrl)breakexcept Exception as e:passwaitWebServerTime -= 1

總結(jié)

現(xiàn)在我們可以直接運(yùn)行main.py,就可以運(yùn)行后端api,并且自動(dòng)打開瀏覽器看到頁(yè)面了~后續(xù)邏輯抽空繼續(xù)寫。

稅務(wù)局電子發(fā)票接口api(圖2)

控制臺(tái)日志

稅務(wù)局電子發(fā)票接口api(圖3)

自動(dòng)打開瀏覽器,訪問(wèn)本地頁(yè)面

代碼比較多,已經(jīng)上傳到github(https://github.com/xy12358/my-invoice-folder.git)和gitee(https://gitee.com/xinying/my-invoice-folder)。

???展開全文
標(biāo)簽: 暫無(wú)
沒(méi)解決問(wèn)題?查閱“相關(guān)文檔”