说起来,这事儿吧,每个刚摸Python想跟MySQL打交道的小伙伴,十有八九都得经历这么一遭:怎么把这俩货给“牵”到一块儿?怎么让我的Python脚本能把数据存进那个黑乎乎的数据库里,或者从里面捞东西出来?别看现在网上教程一大堆,真到自己动手的时候,总会冒出各种幺蛾子,让人抓耳挠腮。今天我就来唠唠,我是怎么一步步爬出这些坑,最终搞定Python连接MySQL这档子事的。
你想啊,我们写Python程序,很多时候可不是光在内存里跑跑就算了的。数据得有个地方安家吧?得持久化吧?尤其是一些需要大量存储、结构化管理数据的场景,MySQL这种关系型数据库简直是标配。那问题来了,我的Python程序怎么才能跟远在天边的(或者就在本地服务器上)MySQL数据库“说话”呢?这中间就需要一个“翻译官”,一个“桥梁”。
这个“翻译官”呢,在Python的世界里,通常就是一些第三方的库。市面上能用来连接MySQL的库有好几个,比如官方推荐的mysql.connector
,还有纯Python实现的PyMySQL
,以及一些更老牌的像MySQLdb
(虽然现在不太推荐新手用了,坑可能多点)。我个人折腾下来,觉得PyMySQL
用起来最省心,尤其对新手来说,安装特方便,纯Python写的,兼容性也不错。当然,mysql.connector
也挺好,官方出品嘛,但有时候安装依赖稍微麻烦那么一丁点。今天咱们就主要说说PyMySQL
吧,因为它真的能让你少走弯路。
第一步,也是最基础的一步,你得先把这个“翻译官”请到你的Python环境里来。这安装啊,简单得不能再简单,打开你的终端或者命令行,敲这么一句:
pip install PyMySQL
回车!等它跑完,出现“Successfully installed PyMySQL”之类的字样,恭喜你,库就装好了。如果遇到权限问题,前面加个sudo
或者用虚拟环境venv啥的,那是另一个话题了,总之,想办法把它装上。
装好库之后,接下来就是见证奇迹的时刻……呸,是真正的连接环节。你想想,去拜访一个人家,你得知道人家的地址、门牌号吧?进门还得有钥匙或者主人给你开门。连接数据库也是一个理儿。你需要告诉Python:
- 数据库服务器在哪儿?(主机地址,通常是IP或者域名,本地的话就是
localhost
或127.0.0.1
) - 哪个端口?(MySQL默认是3306)
- 用哪个用户身份去?(用户名)
- 人家的“钥匙”是啥?(密码)
- 具体要访问哪个数据库?(数据库名)
- 还有个容易被忽略但巨重要的事儿:用啥编码跟它交流?(通常是
utf8mb4
,为了支持emoji啥的,utf8
也行,但得注意是不是真utf8
还是utf8mb4
,MySQL里这俩有时候有点区别,别到时候存个表情变问号,那才叫抓狂!)
有了这些信息,你就可以开始写代码了。打开你的Python编辑器,导入咱们刚装好的PyMySQL:
python
import pymysql
然后,就像打开一扇门一样,去建立那个连接:
“`python
conn = None # 先初始化一下,防止连接失败时conn变量不存在
try:
# 这是连接数据库的关键一步!
conn = pymysql.connect(
host=’your_mysql_host’, # 你的MySQL主机地址,比如 ‘127.0.0.1’ 或 ‘localhost’
port=3306, # 端口号,MySQL默认是3306
user=’your_username’, # 连接MySQL用的用户名
password=’your_password’,# 用户的密码
database=’your_database’,# 要连接的具体数据库名
charset=’utf8mb4′ # 编码方式,超级重要!
# cursorclass=pymysql.cursors.DictCursor # 后面会讲这个,让查询结果变成字典
)
print(“成功连接到MySQL数据库啦!”)
# 接下来就可以搞事情了(执行SQL)
except pymysql.Error as e:
print(f”连接数据库失败!错误信息:{e}”)
无论成功失败,最后都要记得关门
finally:
if conn:
conn.close()
print(“数据库连接已关闭。”)
“`
这段代码里,pymysql.connect()
就是那个发起连接的函数。你需要把那些占位符替换成你自己的MySQL信息。host
, port
, user
, password
, database
, charset
,一个都不能错!尤其是那个charset
,当年我可是吃过不少亏,数据库里存进去是好的,读出来就乱码,或者反过来,都是编码惹的祸。现在我学乖了,一般都直接用utf8mb4
,比较稳妥。
连接建好了,就像你进了人家屋子,但你还没法直接搬东西(执行SQL)。你需要一个“工具”或者“操作员”,这就是所谓的游标(Cursor)。游标是用来执行SQL语句和获取查询结果的。你可以理解成,连接是通道,游标才是真正干活的那个。
通过连接对象创建一个游标很简单:
“`python
假设conn已经成功建立
cursor = conn.cursor()
“`
现在,有了游标,你就可以对着数据库发号施令了!比如你想查点数据:
“`python
定义你的SQL查询语句
sql = “SELECT * FROM users WHERE age > 18”
try:
# 执行SQL语句
cursor.execute(sql)
# 获取查询结果
# fetchone(): 获取单条结果
# fetchall(): 获取所有结果
# fetchmany(size): 获取指定数量的结果
# 比如获取所有结果
results = cursor.fetchall()
# 遍历并打印结果
for row in results:
print(row) # 默认情况下,每行是一个元组(tuple)
except pymysql.Error as e:
print(f”查询失败!错误信息:{e}”)
conn.rollback() # 如果是修改类操作,查询失败一般不用回滚,但写上没坏处
“`
注意看,cursor.execute(sql)
就是执行SQL语句的命令。然后用fetchall()
把所有查到的数据一股脑儿拿回来。默认情况下,拿回来的每一行数据都是一个元组(tuple),里面的字段顺序跟你SELECT
语句里的字段顺序一致。如果你觉得元组不好用,想用字典,可以通过在创建游标的时候指定cursorclass
参数:cursor = conn.cursor(cursorclass=pymysql.cursors.DictCursor)
,这样fetchall()
拿回来的每行就是一个字典了,用字段名当键,取值更方便。
除了查询(SELECT),你肯定还得做点别的,比如插入数据(INSERT)、更新数据(UPDATE)、删除数据(DELETE)。这些操作也都是通过cursor.execute()
来执行SQL语句,但它们跟查询有个巨大的不同:它们会修改数据库里的数据!
“`python
插入一条数据
insert_sql = “INSERT INTO products (name, price) VALUES (%s, %s)” # 注意这里用 %s 作为占位符!
product_data = (‘Python入门到放弃’, 9.9) # 要插入的数据,放到一个元组或列表中
try:
cursor.execute(insert_sql, product_data) # 执行SQL,把数据作为第二个参数传进去!
# 修改数据
update_sql = "UPDATE products SET price = %s WHERE name = %s"
update_data = (19.9, 'Python入门到放弃')
cursor.execute(update_sql, update_data)
# 删除数据
delete_sql = "DELETE FROM products WHERE name = %s"
delete_data = ('Python入门到放弃',) # 注意,只有一个元素的元组后面要加逗号
cursor.execute(delete_sql, delete_data)
#!!! 重点来了!修改、插入、删除操作,执行完execute()之后,数据还在内存里,没有真正写到数据库文件里!
# 你必须进行事务提交,让修改生效!
conn.commit()
print("数据操作成功并已提交!")
except pymysql.Error as e:
print(f”数据操作失败!错误信息:{e}”)
conn.rollback() # 出错了,得把之前没提交的修改都撤销掉,回滚到操作之前的状态!
“`
看到没?插入、更新、删除之后,有个非常关键的步骤:conn.commit()
。这个叫做事务提交。你可以把它想象成,你在数据库里做了修改,这些修改先放在一个临时的“草稿区”里,只有你喊一声“好了,就这样定稿!”,数据库才会把这些修改真正写到硬盘上。如果不commit()
,你的修改就相当于白做了,连接一断开,全没了。
还有个更更更重要的细节,就是那个SQL语句里的%s
!看到了吗?插入、更新、删除甚至带条件的查询,涉及到变量值的地方,千万不要用字符串拼接的方式去构造SQL语句!比如写成"INSERT INTO products (name, price) VALUES ('" + name + "', " + str(price) + ")"
,这可是个大坑!黑客可以利用这种方式进行SQL注入攻击,你的数据库分分钟就被人家玩坏了。正确的姿势是使用占位符(%s
)和execute()方法的第二个参数,把要用的变量值作为元组或列表传进去。PyMySQL
库会自动帮你安全地处理这些值,防止SQL注入。这是数据库操作里最最最基础也是最容易被忽视的安全原则!一定要记牢!
另外,你可能也注意到代码里用到了try...except...finally
。这是处理异常和资源管理的标准姿势。万一连接失败、执行SQL报错、或者其他任何问题,程序不至于崩溃,还能优雅地捕获异常、打印错误信息。而finally
块确保无论如何(无论成功还是失败),连接和游标都能被关闭。为啥要关闭?因为数据库连接是一种有限的资源,开着不用就占着茅坑不拉屎,连接开得太多,数据库服务器会扛不住的。游标也一样,用完了就该清理掉。
不过,比起try...except...finally
里手动关闭,Python里处理这类需要关闭的资源(比如文件、网络连接、数据库连接)有个更优雅、更“Pythonic”的方式,那就是使用with语句。with语句可以保证,在其代码块执行完毕后,无论是否发生异常,相关的资源都会被正确地关闭或释放。用with语句重写上面的连接和操作代码,看起来会更简洁、更安全:
“`python
import pymysql
连接参数
db_config = {
‘host’: ‘your_mysql_host’,
‘port’: 3306,
‘user’: ‘your_username’,
‘password’: ‘your_password’,
‘database’: ‘your_database’,
‘charset’: ‘utf8mb4’
}
try:
# 使用 with 语句建立连接,连接会在 with 块结束时自动关闭
with pymysql.connect(db_config) as conn: # db_config 可以直接传递字典里的参数
# 使用 with 语句创建游标,游标会在 with 块结束时自动关闭
with conn.cursor() as cursor:
print("成功连接并创建游标!")
# 执行查询
select_sql = "SELECT * FROM your_table LIMIT 5"
cursor.execute(select_sql)
results = cursor.fetchall()
print("查询结果:")
for row in results:
print(row)
# 执行插入(示例)
insert_sql = "INSERT INTO another_table (col1, col2) VALUES (%s, %s)"
data_to_insert = [('value1', 100), ('value2', 200)]
# 可以使用 executemany 批量插入
cursor.executemany(insert_sql, data_to_insert)
# 提交事务,让插入生效!
conn.commit()
print(f"成功插入 {cursor.rowcount} 条数据!")
except pymysql.Error as e:
print(f”数据库操作失败!错误信息:{e}”)
if conn: # 检查连接是否成功建立,避免对 None 对象调用 rollback
conn.rollback() # 出错时回滚事务
print(“程序结束,连接已由 with 语句自动关闭。”)
“`
看,是不是简洁多了?with pymysql.connect(...) as conn:
搞定了连接的自动关闭,with conn.cursor() as cursor:
搞定了游标的自动关闭。你只需要操心中间的SQL执行和事务提交(对于修改操作)。这是我强烈推荐的写法!
除了基础的连接、查询、增删改,实际开发中可能还会遇到更复杂的情况。比如高并发场景,每次请求都去新建数据库连接效率太低,而且数据库服务器压力大,这时候就需要连接池(Connection Pool)。连接池就像一个连接的“仓库”,提前创建好一批连接放着,每次需要的时候从池子里取一个可用的,用完还回去,避免了频繁地新建和销毁连接,能显著提升性能。PyMySQL本身不自带连接池,但你可以用第三方库,比如DBUtils
里的PooledDB
或PersistentDB
来实现连接池。
再进一步,如果你觉得直接写SQL语句有点繁琐,或者想让你的Python对象和数据库表之间建立更紧密的联系,你可能会接触到ORM(Object-Relational Mapping,对象关系映射)框架,比如大名鼎鼎的SQLAlchemy。SQLAlchemy可以在更高抽象的层面操作数据库,你可以用面向对象的方式定义你的数据模型,然后通过SQLAlchemy提供的API进行数据库操作,它会负责帮你生成底层的SQL语句,甚至帮你处理连接、事务等细节。虽然ORM不是直接连接数据库本身,但它是许多Python开发者在数据库交互中常用的工具。
总而言之,Python怎么连接MySQL,看起来是件基础的小事,但背后牵扯到库的选择、参数的配置、编码的陷阱、SQL执行的方式、事务的处理、资源的关闭、异常的处理,甚至安全性(SQL注入)和性能优化(连接池)等一系列问题。从最初摸索着写几行代码,到后来明白with语句的好处,再到意识到参数化查询的重要性,每一步都是经验的积累,都是从一个“小白”变成一个“老鸟”的必经之路。
希望我的这些零零碎碎的经验,能帮你少踩几个坑,让你在用Python和MySQL打交道的路上,走得更顺畅一些!记住,遇到问题别慌,看错误信息,查文档,网上搜,总能找到解决办法的。祝你好运!
评论(0)