news 2026/8/30 4:44:52

Python学习日记11

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python学习日记11

数据库支持

13.1 数据库概述

13.1.1 为什么需要数据库

当程序需要存储和管理大量结构化数据时,普通文件(如 CSV、JSON)存在明显局限:

13.1.2 Python 数据库 API(DB API)

Python 提供了统一的数据库接口规范DB API 2.0(PEP 249),不同数据库的 Python 模块遵循相同的 API,让代码可以更容易地切换数据库。

# 统一的使用模式(不因数据库类型而变) import sqlite3 # 或 psycopg2, MySQLdb 等 conn = connect('database.db') # 连接数据库 curs = conn.cursor() # 获取游标 curs.execute('SELECT * FROM table') # 执行 SQL rows = curs.fetchall() # 获取结果 conn.commit() # 提交事务 conn.close() # 关闭连接

13.1.3 常见数据库

13.2 SQLite 快速入门

13.2.1 连接数据库

import sqlite3 # 连接到数据库文件(不存在时会自动创建) conn = sqlite3.connect('mydatabase.db') # 连接内存数据库(临时,程序结束即消失) conn = sqlite3.connect(':memory:') # 关闭连接 conn.close()

13.2.2 游标(Cursor)

游标用于执行 SQL 语句获取查询结果

import sqlite3 conn = sqlite3.connect('mydatabase.db') curs = conn.cursor() # 执行 SQL 语句 curs.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)') # 获取结果 rows = curs.fetchall() conn.close()

13.3 创建表和插入数据

13.3.1 创建表

import sqlite3 conn = sqlite3.connect('mydatabase.db') curs = conn.cursor() # 创建用户表 curs.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, email TEXT UNIQUE ) ''') conn.commit() # 提交更改 conn.close()

SQLite 数据类型

常用约束

13.3.2 插入数据(三种方式)

方式1:直接拼接字符串(不安全,不推荐)

# 危险!容易遭受 SQL 注入攻击 name = "Alice'; DROP TABLE users; --" curs.execute(f"INSERT INTO users (name) VALUES ('{name}')")

方式2:使用参数化查询(推荐)

# 使用 ? 占位符 name = 'Alice' age = 25 curs.execute('INSERT INTO users (name, age) VALUES (?, ?)', (name, age)) # 使用命名占位符 curs.execute('INSERT INTO users (name, age) VALUES (:name, :age)', {'name': 'Bob', 'age': 30})

方式3:批量插入

users = [ ('Charlie', 35), ('Diana', 28), ('Eve', 42), ] curs.executemany('INSERT INTO users (name, age) VALUES (?, ?)', users)

13.3.3 提交事务

conn.commit() # 提交所有更改 # 如果不提交,关闭连接时更改会丢失

13.4 查询数据

13.4.1 基本查询

import sqlite3 conn = sqlite3.connect('mydatabase.db') curs = conn.cursor() # 执行查询 curs.execute('SELECT * FROM users') # 获取所有行(返回列表) all_rows = curs.fetchall() print(all_rows) # [(1, 'Alice', 25, None), (2, 'Bob', 30, None), ...] # 获取一行 one_row = curs.fetchone() # 获取多行(指定数量) few_rows = curs.fetchmany(5) conn.close()

13.4.2 参数化查询

# 查询特定年龄的用户 curs.execute('SELECT * FROM users WHERE age > ?', (25,)) # 查询名字包含特定字符的用户 curs.execute('SELECT * FROM users WHERE name LIKE ?', ('A%',)) # 使用命名参数 curs.execute('SELECT * FROM users WHERE name = :name', {'name': 'Alice'})

13.4.3 使用字典游标

默认返回元组,可以使用字典游标获取带列名的结果。

conn = sqlite3.connect('mydatabase.db') conn.row_factory = sqlite3.Row # 设置为 Row 工厂 curs = conn.cursor() curs.execute('SELECT * FROM users') # 结果可以像字典一样访问 for row in curs.fetchall(): print(row['name'], row['age']) # 或者转换为普通字典 rows = [dict(row) for row in curs.fetchall()]

13.4.4 获取列名

curs.execute('SELECT * FROM users') col_names = [description[0] for description in curs.description] print(col_names) # ['id', 'name', 'age', 'email']

13.5 更新和删除

13.5.1 更新数据

# 更新特定用户 curs.execute('UPDATE users SET age = ? WHERE name = ?', (26, 'Alice')) # 批量更新(所有用户年龄加1) curs.execute('UPDATE users SET age = age + 1') conn.commit()

13.5.2 删除数据

# 删除特定用户 curs.execute('DELETE FROM users WHERE name = ?', ('Eve',)) # 删除所有数据(保留表结构) curs.execute('DELETE FROM users') conn.commit()

13.6 事务处理

13.6.1 事务的概念

事务是一组数据库操作的集合,要么全部成功(提交),要么全部失败(回滚)。

13.6.2 事务示例

import sqlite3 conn = sqlite3.connect('bank.db') curs = conn.cursor() try: # 开始事务(自动开始) curs.execute('UPDATE accounts SET balance = balance - 100 WHERE id = 1') curs.execute('UPDATE accounts SET balance = balance + 100 WHERE id = 2') # 提交事务 conn.commit() print('转账成功') except Exception as e: # 发生错误,回滚所有更改 conn.rollback() print('转账失败,已回滚:', e) finally: conn.close()

13.6.3 自动提交模式

# 默认情况下,sqlite3 使用隐式事务 # 可以启用自动提交(每个操作立即生效) conn = sqlite3.connect('mydatabase.db', isolation_level=None)

13.7 综合示例:营养成分数据库

下面是一个从数据文件导入到 SQLite 数据库并进行查询的完整示例。

13.7.1 数据结构

假设有一个名为ABBREV.txt的数据文件,字段用^分隔,字符串字段用~包围。

~07276~^~HORMEL SPAM...PORK W/ HAM MINCED CND~^...^~1 serving~^^~~^0

13.7.2 导入数据

import sqlite3 def convert(value): """转换字段值""" if value.startswith('~'): return value.strip('~') # 字符串 if not value: return 0 # 空值转为0 return float(value) # 数字 def import_data(filename='ABBREV.txt'): conn = sqlite3.connect('food.db') curs = conn.cursor() # 创建表 curs.execute(''' CREATE TABLE IF NOT EXISTS food ( id TEXT PRIMARY KEY, desc TEXT, water REAL, kcal REAL, protein REAL, fat REAL, ash REAL, carbs REAL, fiber REAL, sugar REAL ) ''') # 插入数据 field_count = 10 query = 'INSERT INTO food VALUES (' + ','.join(['?']*10) + ')' with open(filename, 'r', encoding='utf-8') as f: for line in f: fields = line.split('^') vals = [convert(f) for f in fields[:field_count]] curs.execute(query, vals) conn.commit() conn.close() print(f'数据导入完成')

13.7.3 查询数据

def query_food(condition): """根据条件查询食品数据""" conn = sqlite3.connect('food.db') conn.row_factory = sqlite3.Row curs = conn.cursor() query = f'SELECT * FROM food WHERE {condition}' curs.execute(query) # 获取列名 col_names = [desc[0] for desc in curs.description] # 打印结果 for row in curs.fetchall(): for name in col_names: print(f'{name}: {row[name]}') print() conn.close() # 使用示例:查找低热量高纤维的食品 query_food('kcal <= 100 AND fiber >= 10 ORDER BY sugar')

13.8 SQL 注入防护(重要)

13.8.1 什么是 SQL 注入

SQL 注入是攻击者通过构造恶意输入来执行非预期的 SQL 语句,从而破坏数据库的攻击方式。

# 危险代码 user_input = "Alice'; DROP TABLE users; --" curs.execute(f"SELECT * FROM users WHERE name = '{user_input}'") # 实际执行:SELECT * FROM users WHERE name = 'Alice'; DROP TABLE users; --' # ↑ 恶意代码被注入并执行

13.8.2 防护方法:永远使用参数化查询

# 安全方式:使用参数化查询 user_input = "Alice'; DROP TABLE users; --" curs.execute('SELECT * FROM users WHERE name = ?', (user_input,)) # 参数被当作普通字符串处理,不会执行恶意代码

13.9 本章知识点速查表

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 4:43:43

AI+Obsidian搭建爆款案例库:从素材收集到灵感创作全流程

你有没有过这样的经历&#xff1a;看到一篇爆款文章&#xff0c;当时觉得“这个思路真好”&#xff0c;随手点了收藏&#xff0c;等到自己写内容的时候&#xff0c;却怎么也想不起来它好在哪、结构怎么搭、钩子怎么埋。手机里截图存了上百张&#xff0c;微信收藏里塞满了文章&a…

作者头像 李华
网站建设 2026/8/30 4:43:13

ISM330DHCX机器学习内核深度解析:从决策树原理到低功耗应用实践

我最近在评估ISM330DHCX这颗六轴惯性传感器时&#xff0c;发现很多资料都在强调精度高、功耗低&#xff0c;却很少把真正的杀手锏——机器学习内核&#xff08;MLC&#xff09;讲透。这颗芯片能自己完成从原始信号到分类结果的全部计算&#xff0c;而主机只需要去读一个寄存器&…

作者头像 李华
网站建设 2026/8/30 4:42:57

Referer 校验原理

在 Web 安全与资源管控体系中&#xff0c;Referer 校验是一种成本极低、落地简单的来源身份校验机制&#xff0c;广泛应用于静态资源防盗链、接口访问管控、CSRF 辅助防护等场景。它依托 HTTP 协议原生的请求头字段实现&#xff0c;无需额外开发复杂的认证体系&#xff0c;就能…

作者头像 李华
网站建设 2026/8/30 4:42:24

AVA-Encoder:面向Agent的原生视频表示学习

开头部分&#xff1a;从一次不太顺利的尝试说起。过去一年&#xff0c;我在做一个小型 Agent 项目&#xff1a;让程序看一段操作视频&#xff0c;然后模仿执行其中的关键步骤。第一次尝试很朴素&#xff0c;直接调用现成的视频理解模型&#xff0c;把每一帧截图送进多模态大模型…

作者头像 李华
网站建设 2026/8/30 4:41:47

STM32WB55无法烧录?一文讲透调试接口与读保护排查全流程

1. 先说结论&#xff1a;这不是单一原因&#xff0c;而是一整条故障链STM32WB55出现“cannot be read, erased, programmed”这类报错&#xff0c;十有八九不是芯片物理损坏&#xff0c;而是调试接口状态、Option Bytes配置或双核唤醒机制出了问题。我前前后后经手过十几块WB55…

作者头像 李华
网站建设 2026/8/30 4:40:07

【真0基础0代码AIUI开发教程】不会编程的开发者手把手教你如何开发一个乐奇AI眼镜的AIUI应用

【真0基础0代码AIUI开发教程】不会编程的开发者手把手教你如何开发一个乐奇AI眼镜的AIUI应用 各位乐奇AI眼镜的朋友们&#xff0c;话不多说&#xff0c;让我们正式开搞&#xff0c;本人是一个不会编程的数码爱好者&#xff0c;借助现在的AI编程工具已经开发了若干乐奇眼镜应用…

作者头像 李华