備忘錄_20160105
回首頁
新增
重新整理
定位 100 修改 [2025-04-25] 用 python 來產生 odt 檔案 (20250425-155315)
用 python 來產生 odt 檔案
# pip install odfpy
from odf.opendocument import OpenDocumentText
from odf.table import Table, TableRow, TableCell, TableColumn
from odf.style import Style, PageLayout, PageLayoutProperties, MasterPage
from odf.style import Footer, FooterStyle, ParagraphProperties
from odf.style import TableProperties, TableColumnProperties, TableCellProperties
from odf.style import TextProperties, FontFace
from odf.text import P, Span, PageNumber, PageCount
oDoc=OpenDocumentText()
# 字型
oFontFace=FontFace(name="標楷體", fontfamily="標楷體")
oDoc.fontfacedecls.addElement(oFontFace)
# 版面
oPageLayout=PageLayout(name="pagelayout20250424154200")
oPageLayoutProperties=PageLayoutProperties(
margin="1cm", # 留白 1cm
pagewidth="29.7cm", # A4 橫向
pageheight="21cm", # A4 橫向
printorientation="landscape", # 橫向
writingmode="tb-rl" # 直書
)
oPageLayout.addElement(oPageLayoutProperties)
oDoc.automaticstyles.addElement(oPageLayout)
# 頁尾
oFooterStyle=Style(name="footerstyle20250424140000", family="paragraph")
oFooterStyle.addElement(ParagraphProperties(textalign="center"))
oFooterStyle.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="12pt",fontname="Consolas",fontsize="12pt"))
oDoc.styles.addElement(oFooterStyle)
oFooter=Footer()
oFotterParagraph=P(stylename=oFooterStyle)
oFotterParagraph.addText("2025-04-24 大乘起信論勝異方便")
oFotterParagraph.addText(" ")
oFotterParagraph.addElement(PageNumber(selectpage="current"))
oFotterParagraph.addText(" / ")
oFotterParagraph.addElement(PageCount())
oFooter.addElement(oFotterParagraph)
# 版面+頁尾
oMasterPage=MasterPage(name="Standard", pagelayoutname=oPageLayout)
oMasterPage.addElement(oFooter)
oDoc.masterstyles.addElement(oMasterPage)
# 表格與欄位樣式
oTableStyle=Style(name="tablestyle20250424154200", family="table")
oTableStyle.addElement(TableProperties(width="18cm", align="left"))
oColumnStyle = Style(name="columnstyle20250424154300", family="table-column")
oColumnStyle.addElement(TableColumnProperties(columnwidth="18cm"))
oCellStyleAZero=Style(name="cellstyle20250424163630", family="table-cell")
oCellStyleAZero.addElement(TableCellProperties(backgroundcolor="#D6D5F0", border="0.002cm solid #000000",padding="0.1cm"))
oCellStyleA=Style(name="cellstyle20250424163600", family="table-cell")
oCellStyleA.addElement(TableCellProperties(backgroundcolor="#D6D5F0", borderleft="0.002cm solid #000000",borderright="0.002cm solid #000000",borderbottom="0.002cm solid #000000",padding="0.1cm"))
oCellStyleB=Style(name="cellstyle20250424220700", family="table-cell")
oCellStyleB.addElement(TableCellProperties(backgroundcolor="#ffffff", borderleft="0.002cm solid #000000",borderright="0.002cm solid #000000",borderbottom="0.002cm solid #000000",padding="0.1cm"))
oCellStyleC=Style(name="cellstyle20250424220730", family="table-cell")
oCellStyleC.addElement(TableCellProperties(backgroundcolor="#CDEFF7", borderleft="0.002cm solid #000000",borderright="0.002cm solid #000000",borderbottom="0.002cm solid #000000",padding="0.1cm"))
oCellStyleD=Style(name="cellstyle20250424220800", family="table-cell")
oCellStyleD.addElement(TableCellProperties(backgroundcolor="#ffffff", borderleft="0.002cm solid #000000",borderright="0.002cm solid #000000",borderbottom="0.002cm solid #000000",padding="0.1cm"))
oTextStyleA=Style(name="textstyle20250424165600", family="paragraph")
oTextStyleA.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="12pt",fontweightasian="bold",fontname="標楷體",fontsize="12pt",fontweight="bold"))
oTextStyleB=Style(name="textstyle20250425085700", family="paragraph")
oTextStyleB.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="24pt",fontweightasian="bold",fontname="標楷體",fontsize="24pt",fontweight="bold"))
oTextStyleC=Style(name="textstyle20250425085900", family="paragraph")
oTextStyleC.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="12pt",fontweightasian="bold",fontname="標楷體",fontsize="12pt",fontweight="bold"))
oTextStyleD1=Style(name="textstyle20250425090800", family="paragraph")
oTextStyleD1.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="16pt",fontname="標楷體",fontsize="16pt"))
oTextStyleD1.addElement(ParagraphProperties(backgroundcolor="#dddddd"))
oTextStyleD2=Style(name="textstyle20250425090830", family="paragraph")
oTextStyleD2.addElement(TextProperties(fontnameasian="標楷體",fontsizeasian="12pt",fontname="標楷體",fontsize="12pt"))
oTextStyleD2.addElement(ParagraphProperties(backgroundcolor="#ffffff"))
oDoc.automaticstyles.addElement(oTableStyle)
oDoc.automaticstyles.addElement(oColumnStyle)
oDoc.automaticstyles.addElement(oCellStyleAZero)
oDoc.automaticstyles.addElement(oCellStyleA)
oDoc.automaticstyles.addElement(oCellStyleB)
oDoc.automaticstyles.addElement(oCellStyleC)
oDoc.automaticstyles.addElement(oCellStyleD)
oDoc.automaticstyles.addElement(oTextStyleA)
oDoc.automaticstyles.addElement(oTextStyleB)
oDoc.automaticstyles.addElement(oTextStyleC)
oDoc.automaticstyles.addElement(oTextStyleD1)
oDoc.automaticstyles.addElement(oTextStyleD2)
# 先加入一行空白行
oDoc.text.addElement(P(text=""))
# 表格
oTable = Table(name="table20250424141000", stylename=oTableStyle)
oTable.addElement(TableColumn(stylename=oColumnStyle))
oDoc.text.addElement(oTable)
# 第一格
oRow=TableRow()
oCell=TableCell(stylename=oCellStyleAZero)
oCell.addElement(P(stylename=oTextStyleA, text="大乘起信論勝異方便"))
oRow.addElement(oCell)
oTable.addElement(oRow)
# 第二格
oRow=TableRow()
oCell=TableCell(stylename=oCellStyleB)
oCell.addElement(P(stylename=oTextStyleB, text="[開場白]"))
oRow.addElement(oCell)
oTable.addElement(oRow)
# 第三格
oRow=TableRow()
oCell=TableCell(stylename=oCellStyleC)
oCell.addElement(P(stylename=oTextStyleC, text="講稿與辭典"))
oRow.addElement(oCell)
oTable.addElement(oRow)
# 第四格
oRow=TableRow()
oCell=TableCell(stylename=oCellStyleD)
oCell.addElement(P(stylename=oTextStyleD1, text="請看裂網疏「又識論云。此信心所。自性澄清。亦能淨餘心心所等。如水清珠。能清濁水。」我們先看這一段。"))
oCell.addElement(P(stylename=oTextStyleD2, text="【又】FROM【教育部重編國語辭典修訂本】\r\n[副]1.表示重複或反覆。如:「一天又一天」、「看了又看」。唐.白居易〈賦得古原草送別〉詩:「野火燒不盡,春風吹又生。」"))
oRow.addElement(oCell)
oTable.addElement(oRow)
# 最後加入一行空白行
oDoc.text.addElement(P(text=""))
# 儲存檔案
oDoc.save("20250424_02.odt")
定位 100 修改 [2025-04-24] 用 python 來產生 word 檔案 (20250424-111136)
用 python 來產生 word 檔案
# pip install python-docx
from docx import Document
from docx.shared import Pt
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Cm
from docx.enum.section import WD_ORIENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
def set_table_border(table):
tbl = table._tbl
tblPr = tbl.tblPr
# 建立 <w:tblBorders> 元素
tblBorders = OxmlElement('w:tblBorders')
for border_name in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
border = OxmlElement(f'w:{border_name}')
border.set(qn('w:val'), 'single') # 實線 single
border.set(qn('w:sz'), '1') # 線條寬度,單位為 1/8 pt,1pt=>8,目前用1,等於就是1/8pt
border.set(qn('w:space'), '0') # 線與內容之間距離
border.set(qn('w:color'), '000000') # 黑色
tblBorders.append(border)
# 加入到 <w:tblPr> 中
tblPr.append(tblBorders)
def cm_to_twips(cm):
return int(cm * 567) # 1 cm ≈ 567 twips
def set_table_width(table, width_cm):
table.autofit = False
tbl = table._tbl
tblPr = tbl.tblPr
width_twips = cm_to_twips(width_cm)
tblW = tblPr.xpath('./w:tblW')
if tblW:
tblW[0].set(qn('w:w'), str(width_twips))
tblW[0].set(qn('w:type'), 'dxa')
else:
tblW = OxmlElement('w:tblW')
tblW.set(qn('w:w'), str(width_twips))
tblW.set(qn('w:type'), 'dxa')
tblPr.append(tblW)
def set_table_alignment(table, alignment='center'):
"""
alignment: 'left', 'center', or 'right'
"""
tbl = table._tbl
tblPr = tbl.tblPr
jc = OxmlElement('w:jc')
jc.set(qn('w:val'), alignment)
tblPr.append(jc)
# 插入欄位函式(頁碼、總頁數用)
def insert_field(run, field_code):
fldChar1 = OxmlElement('w:fldChar')
fldChar1.set(qn('w:fldCharType'), 'begin')
instrText = OxmlElement('w:instrText')
instrText.set(qn('xml:space'), 'preserve')
instrText.text = field_code
fldChar2 = OxmlElement('w:fldChar')
fldChar2.set(qn('w:fldCharType'), 'separate')
fldChar3 = OxmlElement('w:fldChar')
fldChar3.set(qn('w:fldCharType'), 'end')
r_element = run._r
r_element.append(fldChar1)
r_element.append(instrText)
r_element.append(fldChar2)
r_element.append(fldChar3)
def set_cell_padding(cell, top=0, left=0, bottom=0, right=0):
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
# 建立 <w:tcMar>(儲存格內距)元素
tcMar = OxmlElement('w:tcMar')
for name, value in (('top', top), ('left', left), ('bottom', bottom), ('right', right)):
mar = OxmlElement(f'w:{name}')
mar.set(qn('w:w'), str(value)) # TWIPS 單位:1 pt = 20,1 cm ≈ 567
mar.set(qn('w:type'), 'dxa')
tcMar.append(mar)
tcPr.append(tcMar)
def set_table_cell_margins(table, margin=0):
"""
設定整張表格的儲存格內距為指定值(預設 0)
"""
tbl = table._tbl
tblPr = tbl.tblPr
tblCellMar = OxmlElement('w:tblCellMar')
for side in ('top', 'start', 'bottom', 'end'):
elem = OxmlElement(f'w:{side}')
elem.set(qn('w:w'), str(margin))
elem.set(qn('w:type'), 'dxa') # dxa = 1/20 pt
tblCellMar.append(elem)
tblPr.append(tblCellMar)
def set_paragraph_background(paragraph, color_hex):
"""
設定段落背景色,例如 color_hex = "FFFF00"(黃色)
"""
p = paragraph._p # 取得底層 <w:p> 元素
pPr = p.get_or_add_pPr() # 取得段落屬性 <w:pPr>
shd = OxmlElement('w:shd') # 建立 <w:shd> 元素
shd.set(qn('w:val'), 'clear') # 填滿方式,clear 表示實心
shd.set(qn('w:color'), 'auto') # 字體顏色(不設定)
shd.set(qn('w:fill'), color_hex) # 背景填滿色
pPr.append(shd) # 加到段落屬性中
def set_cell_background(cell, color_hex):
"""
設定儲存格背景色,例如 color_hex = "FFFF00"(黃色)
"""
tc = cell._tc # 取得底層 <w:tc> 元素
tcPr = tc.get_or_add_tcPr() # 取得 <w:tcPr> 儲存格屬性元素
shd = OxmlElement('w:shd') # 建立 <w:shd> 元素
shd.set(qn('w:val'), 'clear') # 填滿方式
shd.set(qn('w:color'), 'auto') # 不指定字體顏色
shd.set(qn('w:fill'), color_hex) # 背景填滿色
tcPr.append(shd) # 加到儲存格屬性中
# https://python-docx.readthedocs.io/en/latest/
oDoc=Document()
oSection=oDoc.sections[0]
oSection.orientation = WD_ORIENT.PORTRAIT
oSection.page_width = Cm(21)
oSection.page_height = Cm(29.7)
oSection.top_margin = Cm(1)
oSection.bottom_margin = Cm(1)
oSection.left_margin = Cm(1)
oSection.right_margin = Cm(1)
oFooter=oSection.footer
oP=oFooter.paragraphs[0]
oP.alignment = WD_ALIGN_PARAGRAPH.CENTER
oP.text="2025-04-24 大乘起信論勝異方便 "
oRun=oP.add_run()
insert_field(oRun, 'PAGE')
oP.add_run(" / ")
oRun=oP.add_run()
insert_field(oRun, 'NUMPAGES')
oP=oDoc.add_paragraph('')
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oTable=oDoc.add_table(rows=0, cols=1)
oTable.autofit=False
oTable.allow_autofit=False
set_table_alignment(oTable, 'center')
set_table_width(oTable, 18)
set_table_border(oTable)
oP=oDoc.add_paragraph('')
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
# 第一個儲存格
if 1==1:
oCell=oTable.add_row().cells[0]
oCell.width=Cm(18)
set_cell_padding(oCell)
set_cell_background(oCell, 'e7e1fa')
# oP=oCell.paragraphs[0]
# oP=oCell.add_paragraph()
oP=oCell.paragraphs[0]
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oRun=oP.add_run('大乘起信論勝異方便')
oRun.font.name='標楷體'
oRun._element.rPr.rFonts.set(qn('w:eastAsia'), '標楷體')
oRun.font.size=Pt(12)
oRun.font.bold=True
# 第二個儲存格
if 1==1:
oCell=oTable.add_row().cells[0]
oCell.width=Cm(18)
set_cell_padding(oCell)
set_cell_background(oCell, 'ffffff')
# oP=oCell.paragraphs[0]
# oP=oCell.add_paragraph()
oP=oCell.paragraphs[0]
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oRun=oP.add_run('[開場白]')
oRun.font.name='標楷體'
oRun._element.rPr.rFonts.set(qn('w:eastAsia'), '標楷體')
oRun.font.size=Pt(24)
oRun.font.bold=True
# 第三個儲存格
if 1==1:
oCell=oTable.add_row().cells[0]
oCell.width=Cm(18)
set_cell_padding(oCell)
set_cell_background(oCell, 'cbeef7')
# oP=oCell.paragraphs[0]
# oP=oCell.add_paragraph()
oP=oCell.paragraphs[0]
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oRun=oP.add_run('講稿與辭典')
oRun.font.name='標楷體'
oRun._element.rPr.rFonts.set(qn('w:eastAsia'), '標楷體')
oRun.font.size=Pt(12)
oRun.font.bold=True
# 第四個儲存格
if 1==1:
oCell=oTable.add_row().cells[0]
oCell.width=Cm(18)
set_cell_padding(oCell)
set_cell_background(oCell, 'ffffff')
# oP=oCell.paragraphs[0]
# oP=oCell.add_paragraph()
oP=oCell.paragraphs[0]
set_paragraph_background(oP, 'dddddd')
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oRun=oP.add_run("諸位老師學長早安,\r\n阿彌陀佛。")
oRun.font.name='標楷體'
oRun._element.rPr.rFonts.set(qn('w:eastAsia'), '標楷體')
oRun.font.size=Pt(16)
oRun.font.bold=False
# oP=oCell.paragraphs[0]
# oP=oCell.add_paragraph()
oP=oCell.add_paragraph()
oP.paragraph_format.space_before = Pt(0)
oP.paragraph_format.space_after = Pt(0)
oRun=oP.add_run("這裡是辭典文字......")
oRun.font.name='標楷體'
oRun._element.rPr.rFonts.set(qn('w:eastAsia'), '標楷體')
oRun.font.size=Pt(12)
oRun.font.bold=False
######set_table_cell_margins(oTable, 0)
#nmomtf
oDoc.save('20250424.docx')
定位 100 修改 [2025-04-17] python 混合 fastapi 與 tkinter 使用 (20250417-004830)
python 混合 fastapi 與 tkinter 使用
這個程式再修整修整,就可以做出 SaveAs 和 Save(不用再詢問) 了
●save.py
# api
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
from pydantic import BaseModel # 為了 post
# gui
import tkinter as tk
from tkinter import filedialog
# 協同合作
import threading
import queue
import time
import asyncio
oQueue_to_gui = queue.Queue()
oQueue_to_api = queue.Queue()
oStopEvent=threading.Event()
class CData(BaseModel):
strData: str
oMyFastApi = FastAPI()
oMyFastApi.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) # 為了 CORS
@oMyFastApi.get("/stop")
def func_stop():
global oUvicornServer
oStopEvent.set()
oUvicornServer.should_exit=True
return { "訊息": "已送出停止訊息。" }
@oMyFastApi.post("/save")
def func_save(oData: CData):
oQueue_to_gui.put(oData)
while True:
time.sleep(0.1)
if not oQueue_to_api.empty():
strFilename=oQueue_to_api.get_nowait()
break
return { "strFilename": strFilename }
async def run_api():
oConfig=uvicorn.Config(oMyFastApi, host="0.0.0.0", port=8000)
global oUvicornServer
oUvicornServer=uvicorn.Server(oConfig)
await oUvicornServer.serve()
def run_gui():
while not oStopEvent.is_set():
time.sleep(0.1)
if not oQueue_to_gui.empty():
oData=oQueue_to_gui.get_nowait()
oRoot=tk.Tk()
strFilename=filedialog.asksaveasfilename(
title="儲存檔案",
defaultextension=".txt",
filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
)
oQueue_to_api.put(strFilename)
if strFilename!="":
with open(strFilename, "w", encoding="utf-8", newline='') as oFile:
oFile.write(oData.strData)
oRoot.destroy() # 用完關掉 root 視窗
api_thread = threading.Thread(target=lambda: asyncio.run(run_api()), daemon=True)
api_thread.start()
gui_thread = threading.Thread(target=run_gui, daemon=True)
gui_thread.start()
api_thread.join()
gui_thread.join()
●呼叫的 javascript 為
fetch(
'http://127.0.0.1:8000/save',
{
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({ strData: "耶,可以存檔了!\r\n第二行!"})
}
)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
定位 100 修改 [2025-04-15] 在 raspberry pi5 底下,初探 fastapi (20250415-111305)
在 raspberry pi5 底下,初探 fastapi
在 terminal 底下
sudo apt install python3-fastapi
sudo apt install python3-uvicorn
或在虛擬環境的 terminal 底下
pip install fastapi
pip install uvicorn
撰寫一程式,存成 fastapi01.py
------------------------
from fastapi import FastAPI
myapp = FastAPI()
@myapp.get("/hello")
def read_root(name: str, age: int):
return \
{
"message1": f"哈囉, {name}!",
"message2": f"您已經 {age} 歲了."
}
@myapp.get("/money")
def read_root(amount: float):
return \
{
"message3": f"您有 {amount} 元."
}
------------------------
然後執行它
python3 -m uvicorn fastapi01:myapp --reload
或在虛擬環境底下
uvicorn fastapi01:myapp --reload
這時候到瀏覽器去測試
http://127.0.0.1:8000/hello?name=小明&age=38
會得到JSON字串
{"message1":"哈囉, 小明!","message2":"您已經 38 歲了."}
若是輸入
http://127.0.0.1:8000/money?amount=99.87
會得到JSON字串
{"message3":"您有 99.87 元."}
若想要用 https 的話,請先產生憑證
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
這樣可以得到 cert.pem 以及 key.pem
然後執行
python3 -m uvicorn fastapi01:myapp \
--host 0.0.0.0 \
--port 8443 \
--ssl-keyfile=key.pem \
--ssl-certfile=cert.pem
並測試
https://127.0.0.1:8443/hello?name=小王&age=70
https://127.0.0.1:8443/money?amount=99.87
當然,用 apache 的反向代理,那也是一個策略方案。
若要佈署,可以先安裝 pyinstaller
在虛擬環境底下
pip install pyinstaller
然後執行
pyinstaller fastapi01.py --onefile
那麼,執行檔會在 dist/fastapi01
但是,因為 fastapi01 是用 uvicorn 執行的,所以這樣封裝出來的執行檔不能用。
要改成自己用 uvicorn 執行,請參考 fastapi02.py
-------------------------------------
from fastapi import FastAPI
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
myapp = FastAPI()
# 這個可以通過 CORS 政策
myapp.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
@myapp.get("/hello")
def read_root(name: str, age: int):
return \
{
"message1": f"哈囉, {name}!",
"message2": f"您已經 {age} 歲了."
}
@myapp.get("/money")
def read_root(amount: float):
return \
{
"message3": f"您有 {amount} 元."
}
if __name__ == "__main__":
uvicorn.run(
myapp,
host="0.0.0.0",
port=8000)
-------------------------------------
這個時候,就可以用 python fastapi02.py 執行。
若用 pyinstaller fastapi02.py --onefile 封裝
則 dist/fastapi02 就可以常駐執行。
您可以寫一個 html 來測試
<!DOCTYPE html>
<html>
<head>
<title>Test Fetch</title>
</head>
<body>
<script>
fetch('http://127.0.0.1:8000/money?amount=3838')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
</script>
</body>
</html>
當你在 windows 7 底下進行編譯
pyinstaller fastapi02.py --onefile
結果在執行 dist/fastapi02.exe 時
會遇到錯誤訊息 "ImportError: DLL load failed while importing _pydantic_core: 找不到指定的程序。"
原來 FastAPI 依賴 pydantic,而 pydantic v2.x 對 win7 的支援度很差,所以可以用降版處理。
pip uninstall pydantic
pip install pydantic==1.10.13
(目前的 FastAPI 仍支援 pydantic v1.x)
pyinstaller fastapi02.py --onefile
這樣編出來的 dist/fastapi02.exe 就可以在 win7 執行了!
假如要用 POST 方法,則撰寫 fastapi03.py
------------------------------------
from fastapi import FastAPI
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
class MyItem(BaseModel):
name: str
price: float
myapp = FastAPI()
# 這個可以通過 CORS 政策
myapp.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
@myapp.post("/items")
def create_item(myitem: MyItem):
return \
{
"myname": myitem.name,
"myprice": myitem.price
}
@myapp.get("/hello")
def read_root(name: str, age: int):
# 需要的參數若使用者提供不齊全,會產生錯誤訊息!
return \
{
"message1": f"哈囉, {name}!",
"message2": f"您已經 {age} 歲了."
}
@myapp.get("/money")
def read_root(amount: float):
return \
{
"message3": f"您有 {amount} 元."
}
if __name__ == "__main__":
uvicorn.run(
myapp,
host="0.0.0.0",
port=8000)
------------------------------------
然後用 python fastapi03.py 執行
再來是在 javascript 的部分,用下面方法測試。
------------------------------------
fetch(
'http://127.0.0.1:8000/items',
{
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({ name: "John", price: 500})
}
)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
------------------------------------
注意,用 fastapi 的 get 或 post 方法,
使用者提供的參數一定要足夠,可以多,不能少,
若是在 python 端需要 5 個參數,
結果使用者端只提供 4 個參數,
那麼程式不會往後執行,只會跳出參數不足的錯誤訊息。
另外,用 http://127.0.0.1:8000/docs
竟然會列出所有的 get/post 方法與參數,
這真是太神奇了!
定位 100 修改 [2025-04-11] raspberry pi 5 設定 winkey+m 可以將所有視窗縮小,顯示桌面 (20250411-100614)
raspberry pi 5 設定 winkey+m 可以將所有視窗縮小,顯示桌面
可以用 echo $DESKTOP_SESSION 知道目前使用的桌面環境為何。
使用 echo $XDG_CURRENT_DESKTOP 也是可以的。
例如 LXDE-pi 就是其中一種。(未綁定 winkey 為特殊功能)
首先在 /home/pi 當中
sudo geany show_desktop.sh
裡面內容如下
#!/bin/bash
# 最小化所有開啟的視窗
for win in $(xdotool search --onlyvisible --class .); do
xdotool windowminimize $win
done
存檔後,賦予執行權限 sudo chmod +x show_desktop.sh
若執行 ./show_desktop.sh 就會發現,所有視窗都縮小了。
你有可能需要先安裝 xdotool
sudo apt install xdotool
接下來,設定作業系統層級的快速鍵
sudo geany .config/openbox/lxde-pi-rc.xml
在 <keyboard>......</keybaord> 裡面,加入下面內容
<keybind key="W-m">
<action name="Execute">
<command>/home/pi/show_desktop.sh</command>
</action>
</keybind>
存檔後,進行刷新
openbox --reconfigure
這時候,就可以隨時用 Winkey+M 來縮小視窗了!
同樣是 raspberry pi 5
也有遇到 winkey 是呼叫出系統選單,這時候要 winkey+m 兩次,很煩。
不過,同時,用 Ctrl+Alt+D 卻意外好用,也可以試試看。
Finished.