Python 开发笔记

目录

- 根据已有数据表生成实体模型类

- 字典合并

- 与asyncio一起,在TCP服务端检查客户端是否断连

- * 与 ** 的用法

- 初始化venv环境

- pip

- 避免安装时出现 "python setup.py egg_info did not run successfully." 问题

- linux下安装tkinter包

- 将库中的python模块用作脚本去运行

- vscode中的launch.json

- 项目根目录定义

- 函数参数中的/和*

- 类型转换

- 关于pytest

- fastapi中的数据分页

- 添加应用运行路径 

- 导出数据库到一个Excel文件

- 运算符


- 根据已有数据表生成实体模型类

法一: 使用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

 参考: sqlacodegen-v2 · PyPI

法二: 使用 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 "接口异常!"

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bennybi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值