目录
- 避免安装时出现 "python setup.py egg_info did not run successfully." 问题
- 根据已有数据表生成实体模型类
法一: 使用sqlacodegen生成数据模型类, 注意使用2.0版本(sqlacodegen-v2 · PyPI)
# pip install sqlacodegen-v2
# Example:
sqlacodegen_v2 postgresql:///some_local_db
sqlacodegen_v2 --generator tables mysql+pymysql://user:password@localhost/dbname --outfile=models.py
sqlacodegen_v2 --generator dataclasses sqlite:///database.db
说明 | 命令 |
生成基于declarative_base的模型类 declarative (the default; generates classes inheriting from declarative_base() | sqlacodegen_v2 --generator declarative mysql+pymysql://user:password@localhost/dbname --outfile=models.py |
生成对表操作的对象 tables (only generates Table objects, for those who don’t want to use the ORM) | sqlacodegen_v2 --generator tables mysql+pymysql://user:password@localhost/dbname --outfile=models.py |
使用超类 MappedAsDataclass 生成声明性模型,不继承Base declarative-dataclasses (generate declarative model with Superclass MappedAsDataclass) | sqlacodegen_v2 --generator declarative-dataclasses mysql+pymysql://user:password@localhost/dbname --outfile=models.py |
dataclasses (generates dataclass-based models; v1.4+ only) | sqlacodegen_v2 --generator dataclasses mysql+pymysql://user:password@localhost/dbname --outfile=models.py |
生成继承自SQLModel 的模型类 sqlmodels (generates model classes for SQLModel) | sqlacodegen_v2 --generator sqlmodels mysql+pymysql://user:password@localhost/dbname --outfile=models.py |
法二: 使用 flask-sqlacodegen
参考: python flask-SQLAlchemy通过数据库表反向生成model模型_flask生成model代码-CSDN博客
- 字典合并
浅层合并(适用于1层字典,多于1层的键值会直接替代原值):
法1:
dict1.update(b=2, c=3, d=4)
法2:
merged_dict = {**d1, **d2, **{"k1": "v1", "k2": "v2"}, **d3}
法3:python3.9 后支持合并符号 "|"
md1 = d1 | d2 | d3
print(md1)
深层合并(适用于多层字典):
from deepmerge import always_merger
# 示例字典
d1 = {"Qin": "YingZheng", "Han": "LiuBang", "Sui": "YangJian", "Tang": "LY", "embed1":{'a1': 2, 'a2': {'b1': 2, 'b2': 3}}}
d2 = {"Tang": "zzz", "embed1":{'a1': 88, 'a2': {'b1': 88}}}
# 使用 deepmerge 进行深层合并
md2 = always_merger.merge(d1, d2)
print(md2)
# 输出:
{'Qin': 'YingZheng', 'Han': 'LiuBang', 'Sui': 'YangJian', 'Tang': 'zzz', 'embed1': {'a1': 88, 'a2': {'b1': 88, 'b2': 3}}}
# 如果是浅层合并, 只会输出
{'Qin': 'YingZheng', 'Han': 'LiuBang', 'Sui': 'YangJian', 'Tang': 'zzz', 'embed1': {'a1': 88, 'a2': {'b1': 88}}}
- 与asyncio一起,在TCP服务端检查客户端是否断连
async def main():
server = await asyncio.start_server(handle_client, "0.0.0.0", 9888)
# Set TCP keep-alive on the listening socket
sock = server.sockets[0]
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1
) # enable keepalive mechanism
if hasattr(socket, "TCP_KEEPIDLE"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 2) # after_idle_sec
if hasattr(socket, "TCP_KEEPINTVL"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 1) # interval_sec
if hasattr(socket, "TCP_KEEPCNT"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 2) # max_fails
addr = server.sockets[0].getsockname()
print(f"Serving on {addr}")
async with server:
await server.serve_forever()
- * 与 ** 的用法
# 1. 函数传递参数
*args 表示任何多个无名参数,它本质是一个 tuple
**kwargs 表示关键字参数,它本质上是一个 dict
# 2. 调用函数时,在传入的参数前加上*表示对参数进行分解,前提是参数可迭代(Iterable)
print(*list)
- 初始化venv环境
python -m venv .venv
# win32下激活
.venv/Script/activate
# Linux下激活
source .venv/bin/activate
- pip
在Windows下安装一些LLM工具时,需要启动系统长目录名支持,执行:
# https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell#enable-long-paths-in-windows-10-version-1607-and-later
# PowerShell
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
# 查看配置
pip config list
# 设置国内清华镜像源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 安装时临时加镜像源 (清华源很快且全)
pip install -r requirements.txt https://pypi.tuna.tsinghua.edu.cn/simple
# 升级pip
python -m pip install --user --upgrade pip
# 安装依赖包清单
pip install -r requirements.txt
# 生成依赖包清单
pip freeze > requirements.txt
- 避免安装时出现 "python setup.py egg_info did not run successfully." 问题
pip install setuptools-scm
pip install seqeval
- linux下安装tkinter包
apt-get install python3-tk
- 将库中的python模块用作脚本去运行
python -m uvicorn main:app --reload
- vscode中的launch.json
# 等同于执行 python main.py run 命令行
{
"configurations": [
{
"name":"Run Project",
"type":"python",
"request":"launch",
"program":"main.py",
"args":["run"],
"console":"integratedTerminal",
"justMyCode":true
}
]
}
# fastapi带路径的模块执行
{
"name":"Run Fastapi",
"type":"python",
"request":"launch",
"cwd": "${workspaceFolder}/fastapi",
"module": "uvicorn",
"args": ["t1:app","--reload"]
}
- 项目根目录定义
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- 函数参数中的/和*
# 参数位置只能使用位置参数而不能使用关键字参数传参, 在该参数后加 /
def f1(a, b, /):
return a + b
# 必须以关键字参数的形式传参,在其前加 *
# b, c 调用时必须给出: print(f1(1, b=3, c=4))
def f(a, *, b, c):
return a + b + c
- 类型转换
int(x [,base])
print(int(3.6))
print(int("1001",2))
print(int("0xa",16))
# 将10进制整数转换成16进制,以字符串形式表示
hex(x)
print(hex(255),hex(-42),hex(1),hex(12),type(hex(12)))
str(x)
s1 = 'python'
s2 = {'python': 'python.com', 'google': 'google.com'}
print(str(s1),str(s2))
# 将对象转化为供解释器读取的形式
repr(x)
s1 = 'python'
s2 = {'python': 'python.com', 'google': 'google.com'}
print(repr(s1),repr(s2))
# 将可迭代系列(如列表)转换为元组
tuple(x)
l1 = ['python', 'ruby', 'golang', 'java']
t1 = tuple(l1)
print(t1)
# 将元组或字符串转换为列表
list(x)
t1 = (123, 'Google', 'Python', 'Taobao')
l1 = list(t1)
s1 = "hello"
l2 = list(s1)
print(l1,l2)
# 创建一个无序不重复元素集,可进行关系测试,删除重复数据
set(x)
l1 = ['a', 'b', 'b', 'c', 'c', 'c']
s1 = set(l1)
print(s1)
# 创建一个字典,d 必须是一个 (key, value)元组序列
dict(d)
d1 = dict(a='a', b='b', t='t') #传入关键字
d2 = dict(zip(['one', 'two', 'three'], [1, 2, 3])) #映射函数方式来构造字典
d3 = dict([('one', 1), ('two', 2), ('three', 3)]) #可迭代对象方式来构造字典
print(d1)
print(d2)
print(d3)
# 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素
frozenset(s)
f1 = frozenset(range(10))
f2 = frozenset(['h','e','l','l','0'])
print(f1)
print(f2)
- 关于pytest
- test_*.py 文件里对模块.包的引用不要用相对路径引入, 否则会出现“ImportError: attempted relative import beyond top-level package” 之类的错误提示
# wrong from ..apps.main import app # right from apps.main import app
-
可在项目根目录定义pytest.ini配置测试文件夹路径等, pytest.ini
[pytest] testpaths=tests
- fastapi中的数据分页
# 安装所需模块
pip install sqlacodegen-v2
pip install fastapi-pagination
pip install sqlakeyset
# Example:
# 其中schemas.User 是pydantic 负责输入输出的模型,models.User是sqlalchemy数据模型
@app.get("/users-db")
def get_users_db(db: Session = Depends(get_db)) -> Page[schemas.User]:
return paginate(db, select(models.User).order_by(models.User.id))
# schemas.User
class User(UserBase):
id: int
is_active: bool
items: list[Item] = []
class Config:
from_attributes = True
# models.User
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
email = Column(String(50), unique=True, index=True)
hashed_password = Column(String(50),)
is_active = Column(Boolean, default=True)
items = relationship("Item", back_populates="owner")
- 添加应用运行路径
有时候运行某框架/应用下的脚本时,因不在项目根目录上运行,直接走会报如:ModuleNotFoundError: No module named 'application'之类的错误,需在脚本里把应用路径给加上解决:
import os.path
import sys
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), '../../'))
- 导出数据库到一个Excel文件
import pandas as pd
import mysql.connector
from sqlalchemy import create_engine, text
# 数据库连接参数
db_connection_params = {
'user': 'aaa',
'password': 'bbb',
'host': 'ccc,
'database': 'ddd'
}
# 创建数据库连接
engine = create_engine(f"mysql+mysqlconnector://{db_connection_params['user']}:{db_connection_params['password']}@{db_connection_params['host']}/{db_connection_params['database']}")
# 获取所有表名
with engine.connect() as conn:
result = conn.execute(text("SHOW TABLES;"))
table_names = [row[0] for row in result]
# 使用Pandas的Excel writer和openpyxl作为引擎
with pd.ExcelWriter('./DbToExcel/exported_tables.xlsx', engine='openpyxl') as writer:
for table_name in table_names:
# 读取表
df = pd.read_sql_table(table_name, con=engine)
# 将表写入Excel文件中的单独工作表
df.to_excel(writer, sheet_name=table_name[:31], index=False) # Excel工作表名不能超过31字符
# 关闭数据库连接
engine.dispose()
- 运算符
# 三目运算符
return error.__str__() if DEBUG else "接口异常!"
- Windows中的异步事件循环
从 Python 3.8 开始,默认的异步事件循环是 ProactorEventLoop。该循环不支持 aiomqtt 所需的 add_reader 方法。请切换到支持add_reader方法的事件循环,例如内置的SelectorEventLoop:
# Change to the "Selector" event loop if platform is Windows
if sys.platform.lower() == "win32" or os.name.lower() == "nt":
from asyncio import set_event_loop_policy, WindowsSelectorEventLoopPolicy
set_event_loop_policy(WindowsSelectorEventLoopPolicy())
# Run your async application as usual
asyncio.run(main())
- Logging
import logging
...
# 设置格式
log_format = "%(message)s"
logging.basicConfig(
filename=f"{BASE_DIR}/logs/k1.log", format=log_format, level=logging.INFO
)
...
logging.info("{}".format(json_data))