Python之pymysql的使用小结


Posted in Python onJuly 01, 2019

在python3.x中,可以使用pymysql来MySQL数据库的连接,并实现数据库的各种操作,本次博客主要介绍了pymysql的安装和使用方法。

 PyMySQL的安装

一、.windows上的安装方法:

在python3.6中,自带pip3,所以在python3中可以直接使用pip3去安装所需的模块:

pip3 install pymysql -i https://pypi.douban.com/simple

二、.linux下安装方法:

1.tar包下载及解压

下载tar包
wget https://pypi.python.org/packages/29/f8/919a28976bf0557b7819fd6935bfd839118aff913407ca58346e14fa6c86/PyMySQL-0.7.11.tar.gz#md5=167f28514f4c20cbc6b1ddf831ade772
解压并展开tar包
tar xf PyMySQL-0.7.11.tar.gz

2.安装

[root@localhost PyMySQL-0.7.11]# python36 setup.py install

数据库的连接

本次测试创建的数据及表:

#创建数据库及表,然后插入数据
mysql> create database dbforpymysql;
mysql> create table userinfo(id int not null auto_increment primary key,username varchar(10),passwd varchar(10))engine=innodb default charset=utf8;
mysql> insert into userinfo(username,passwd) values('frank','123'),('rose','321'),('jeff',666);

#查看表内容
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank  | 123  |
| 2 | rose   | 321  |
| 3 | jeff   | 666  |
+----+----------+--------+
3 rows in set (0.00 sec)

连接数据库:

import pymysql

#连接数据库
db = pymysql.connect("localhost","root","LBLB1212@@","dbforpymysql")

#使用cursor()方法创建一个游标对象
cursor = db.cursor()

#使用execute()方法执行SQL语句
cursor.execute("SELECT * FROM userinfo")

#使用fetall()获取全部数据
data = cursor.fetchall()

#打印获取到的数据
print(data)

#关闭游标和数据库的连接
cursor.close()
db.close()

#运行结果
((1, 'frank', '123'), (2, 'rose', '321'), (3, 'jeff', '666'))

要完成一个MySQL数据的连接,在connect中可以接受以下参数:

def __init__(self, host=None, user=None, password="",
       database=None, port=0, unix_socket=None,
       charset='', sql_mode=None,
       read_default_file=None, conv=None, use_unicode=None,
       client_flag=0, cursorclass=Cursor, init_command=None,
       connect_timeout=10, ssl=None, read_default_group=None,
       compress=None, named_pipe=None, no_delay=None,
       autocommit=False, db=None, passwd=None, local_infile=False,
       max_allowed_packet=16*1024*1024, defer_connect=False,
       auth_plugin_map={}, read_timeout=None, write_timeout=None,
       bind_address=None):
参数解释:
host: Host where the database server is located  #主机名或者主机地址
user: Username to log in as  #用户名
password: Password to use.  #密码
database: Database to use, None to not use a particular one.  #指定的数据库
port: MySQL port to use, default is usually OK. (default: 3306)  #端口,默认是3306
bind_address: When the client has multiple network interfaces, specify
  the interface from which to connect to the host. Argument can be
  a hostname or an IP address.  #当客户端有多个网络接口的时候,指点连接到数据库的接口,可以是一个主机名或者ip地址
unix_socket: Optionally, you can use a unix socket rather than TCP/IP.
charset: Charset you want to use.  #指定字符编码
sql_mode: Default SQL_MODE to use. 
read_default_file:
  Specifies my.cnf file to read these parameters from under the [client] section.
conv:
  Conversion dictionary to use instead of the default one.
  This is used to provide custom marshalling and unmarshaling of types.
  See converters.
use_unicode:
  Whether or not to default to unicode strings.
  This option defaults to true for Py3k.
client_flag: Custom flags to send to MySQL. Find potential values in constants.CLIENT.
cursorclass: Custom cursor class to use.
init_command: Initial SQL statement to run when connection is established.
connect_timeout: Timeout before throwing an exception when connecting.
  (default: 10, min: 1, max: 31536000)
ssl:
  A dict of arguments similar to mysql_ssl_set()'s parameters.
  For now the capath and cipher arguments are not supported.
read_default_group: Group to read from in the configuration file.
compress; Not supported
named_pipe: Not supported
autocommit: Autocommit mode. None means use server default. (default: False)
local_infile: Boolean to enable the use of LOAD DATA LOCAL command. (default: False)
max_allowed_packet: Max size of packet sent to server in bytes. (default: 16MB)
  Only used to limit size of "LOAD LOCAL INFILE" data packet smaller than default (16KB).
defer_connect: Don't explicitly connect on contruction - wait for connect call.
  (default: False)
auth_plugin_map: A dict of plugin names to a class that processes that plugin.
  The class will take the Connection object as the argument to the constructor.
  The class needs an authenticate method taking an authentication packet as
  an argument. For the dialog plugin, a prompt(echo, prompt) method can be used
  (if no authenticate method) for returning a string from the user. (experimental)
db: Alias for database. (for compatibility to MySQLdb)
passwd: Alias for password. (for compatibility to MySQLdb)

cursor其实是调用了cursors模块下的Cursor的类,这个模块主要的作用就是用来和数据库交互的,当你实例化了一个对象的时候,你就可以调用对象下面的各种绑定方法:

class Cursor(object):
  """
  This is the object you use to interact with the database.
  """
  def close(self):
    """
    Closing a cursor just exhausts all remaining data.
    """
  def setinputsizes(self, *args):
    """Does nothing, required by DB API."""

  def setoutputsizes(self, *args):
    """Does nothing, required by DB API."""    
  def execute(self, query, args=None):
    """Execute a query

    :param str query: Query to execute.

    :param args: parameters used with query. (optional)
    :type args: tuple, list or dict

    :return: Number of affected rows
    :rtype: int

    If args is a list or tuple, %s can be used as a placeholder in the query.
    If args is a dict, %(name)s can be used as a placeholder in the query.
    """
  def executemany(self, query, args):
    # type: (str, list) -> int
    """Run several data against one query

    :param query: query to execute on server
    :param args: Sequence of sequences or mappings. It is used as parameter.
    :return: Number of rows affected, if any.

    This method improves performance on multiple-row INSERT and
    REPLACE. Otherwise it is equivalent to looping over args with
    execute().
    """
  def fetchone(self):
    """Fetch the next row"""
  def fetchmany(self, size=None):
    """Fetch several rows"""
  def fetchall(self):
    """Fetch all the rows"""
  ......

数据库操作

一、数据库增删改操作

commit()方法:在数据库里增、删、改的时候,必须要进行提交,否则插入的数据不生效。

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES('jack','123')"
cursor.execute(sql)
db.commit() #提交数据
cursor.close()
db.close()
或者在execute提供插入的数据
import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.execute(sql,("bob","123")) 
db.commit() #提交数据
cursor.close()
db.close()

小知识点,mysql的注入问题:

在mysql中使用"--"代表注释,比如现在来实现一个用户登录的小程序:
用户名和密码都存在表userinfo中,表内容如下:
mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank  | 123  |
| 2 | rose   | 321  |
| 3 | jeff   | 666  |
+----+----------+--------+
3 rows in set (0.00 sec)
小程序代码如下:
import pymysql
user = input("username:")
pwd = input("password:")
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from userinfo where username='%s' and passwd='%s'" %(user,pwd)
result=cursor.execute(sql)
cursor.close()
db.close()
if result:
  print('登录成功')
else:
  print('登录失败')
#正确登录的运行结果
username:frank
password:123
result: 1
登录成功
#错误登录的运行结果
username:frank
password:1231231
result: 0
登录失败
看起来没有什么问题,但是试试下面的方式吧
----------------------------------------------
username:' or 1=1 -- 
password:123
result: 3
登录成功
----------------------------------------------
咦~也登录成功了.
为什么呢?可以看一下现在的执行的sql语句:
select * from userinfo where username='' or 1=1 -- ' and passwd='123'
这里--后面的会被注释,所以where一定会成功,这里等于查看了所有行的内容,返回值也不等于0,所以就登录成功了。
解决方法就是将变量或者实参直接写到execute中即可:
result=cursor.execute(sql,(user,pwd))
在键入类似' or 1=1 -- 的时候就不会登录成功了。

executemany():用来同时插入多条数据:

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.executemany(sql,[("tom","123"),("alex",'321')])
db.commit() #提交数据
cursor.close()
db.close()

execute()和executemany()都会返回受影响的行数:

sql = "delete from userinfo where username=%s"
res = cursor.executemany(sql,("jack",))
print("res=",res)
#运行结果
res= 1

当表中有自增的主键的时候,可以使用lastrowid来获取最后一次自增的ID:

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
cursor.execute(sql,("zed","123"))
print("the last rowid is ",cursor.lastrowid)
db.commit() #提交数据
cursor.close()
db.close()

#运行结果
the last rowid is 10

二、数据库的查询操作

这里主要介绍三个绑定方法:

  • fetchone():获取下一行数据,第一次为首行;
  • fetchall():获取所有行数据源
  • fetchmany(4):获取下4行数据

先来查看表的内容:

mysql> select * from userinfo;
+----+----------+--------+
| id | username | passwd |
+----+----------+--------+
| 1 | frank  | 123  |
| 2 | rose   | 321  |
| 3 | jeff   | 666  |
| 5 | bob   | 123  |
| 8 | jack   | 123  |
| 10 | zed   | 123  |
+----+----------+--------+
6 rows in set (0.00 sec)

使用fetchone():

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchone() #第一次执行
print(res)
res = cursor.fetchone() #第二次执行
print(res)
cursor.close()
db.close()

#运行结果
(1, 'frank', '123')
(2, 'rose', '321')

使用fetchall():

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall() #第一次执行
print(res)
res = cursor.fetchall() #第二次执行
print(res)
cursor.close()
db.close()
#运行结果
((1, 'frank', '123'), (2, 'rose', '321'), (3, 'jeff', '666'), (5, 'bob', '123'), (8, 'jack', '123'), (10, 'zed', '123'))
()

可以看到,第二次获取的时候,什么数据都没有获取到,这个类似于文件的读取操作。

默认情况下,我们获取到的返回值是元组,只能看到每行的数据,却不知道每一列代表的是什么,这个时候可以使用以下方式来返回字典,每一行的数据都会生成一个字典:

cursor = db.cursor(cursor=pymysql.cursors.DictCursor) #在实例化的时候,将属性cursor设置为pymysql.cursors.DictCursor

使用fetchall获取所有行的数据,每一行都被生成一个字典放在列表里面:

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall()
print(res)
cursor.close()
db.close()
#运行结果
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]

这样获取到的内容就能够容易被理解和使用了!

在获取行数据的时候,可以理解开始的时候,有一个行指针指着第一行的上方,获取一行,它就向下移动一行,所以当行指针到最后一行的时候,就不能再获取到行的内容,所以我们可以使用如下方法来移动行指针:

cursor.scroll(1,mode='relative') # 相对当前位置移动
cursor.scroll(2,mode='absolute') # 相对绝对位置移动

第一个值为移动的行数,整数为向下移动,负数为向上移动,mode指定了是相对当前位置移动,还是相对于首行移动

例如:

sql = "SELECT * FROM userinfo"
cursor.execute(sql)
res = cursor.fetchall()
print(res)
cursor.scroll(0,mode='absolute') #相对首行移动了0,就是把行指针移动到了首行
res = cursor.fetchall() #第二次获取到的内容
print(res)

#运行结果
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]
[{'id': 1, 'username': 'frank', 'passwd': '123'}, {'id': 2, 'username': 'rose', 'passwd': '321'}, {'id': 3, 'username': 'jeff', 'passwd': '666'}, {'id': 5, 'username': 'bob', 'passwd': '123'}, {'id': 8, 'username': 'jack', 'passwd': '123'}, {'id': 10, 'username': 'zed', 'passwd': '123'}]

上下文管理器

在python的文件操作中支持上下文管理器,在操作数据库的时候也可以使用:

import pymysql
config={
  "host":"127.0.0.1",
  "user":"root",
  "password":"LBLB1212@@",
  "database":"dbforpymysql"
}
db = pymysql.connect(**config)
with db.cursor(cursor=pymysql.cursors.DictCursor) as cursor: #获取数据库连接的对象
  sql = "SELECT * FROM userinfo"  
  cursor.execute(sql)
  res = cursor.fetchone()
  print(res)
  cursor.scroll(2,mode='relative')
  res = cursor.fetchone()
  print(res)
  cursor.close()
db.close()

#运行结果
{'id': 1, 'username': 'frank', 'passwd': '123'}
{'id': 5, 'username': 'bob', 'passwd': '123'}

上下文管理器可以使代码的可读性更强。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
详解Python中__str__和__repr__方法的区别
Apr 17 Python
用python的requests第三方模块抓取王者荣耀所有英雄的皮肤实例
Dec 14 Python
Python制作豆瓣图片的爬虫
Dec 28 Python
Python中getpass模块无回显输入源码解析
Jan 11 Python
python编程测试电脑开启最大线程数实例代码
Feb 09 Python
Python3爬虫爬取百姓网列表并保存为json功能示例【基于request、lxml和json模块】
Dec 05 Python
python中dir()与__dict__属性的区别浅析
Dec 10 Python
python使用xlsxwriter实现有向无环图到Excel的转换
Dec 12 Python
总结python中pass的作用
Feb 27 Python
Python爬虫后获取重定向url的两种方法
Jan 19 Python
Python实现GIF动图以及视频卡通化详解
Dec 06 Python
详解OpenCV获取高动态范围(HDR)成像
Apr 29 Python
linux下安装python3和对应的pip环境教程详解
Jul 01 #Python
python写日志文件操作类与应用示例
Jul 01 #Python
python实现自动化上线脚本的示例
Jul 01 #Python
在Python中构建增广矩阵的实现方法
Jul 01 #Python
django框架实现模板中获取request 的各种信息示例
Jul 01 #Python
Python整数对象实现原理详解
Jul 01 #Python
python实现两个dict合并与计算操作示例
Jul 01 #Python
You might like
php生成随机密码的三种方法小结
2010/09/04 PHP
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
PHP序列化操作方法分析
2016/09/28 PHP
Yii实现复选框批量操作实例代码
2017/03/15 PHP
通过正则表达式实现表单验证是否为中文
2014/02/18 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
完美实现八种js焦点轮播图(上篇)
2016/07/18 Javascript
nodejs个人博客开发第五步 分配数据
2017/04/12 NodeJs
javascript定时器取消定时器及优化方法
2017/07/08 Javascript
原生js的ajax和解决跨域的jsonp(实例讲解)
2017/10/16 Javascript
浅谈SpringMVC中post checkbox 多选框value的值(隐藏域方式)
2018/01/08 Javascript
Koa日志中间件封装开发详解
2019/03/09 Javascript
countUp.js实现数字滚动效果
2019/10/18 Javascript
webpack+vue-cil 中proxyTable配置接口地址代理操作
2020/07/18 Javascript
[41:05]Serenity vs Pain 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python读取html中指定元素生成excle文件示例
2014/04/03 Python
Python基于PycURL实现POST的方法
2015/07/25 Python
SQLite3中文编码 Python的实现
2017/01/11 Python
python实现画圆功能
2018/01/25 Python
python中的json总结
2018/10/11 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
强悍的Python读取大文件的解决方案
2019/02/16 Python
python中sort和sorted排序的实例方法
2019/08/26 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
2020/06/18 Python
Python中的流程控制详解
2021/02/18 Python
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
AmazeUI 等分网格的实现示例
2020/08/25 HTML / CSS
雅诗兰黛(Estee Lauder)英国官方网站:世界顶级化妆品牌
2016/12/29 全球购物
安踏官方商城:anta.cn
2019/12/16 全球购物
卡拉威高尔夫官方网站:Callaway Golf
2020/09/16 全球购物
如何提高SQL Server的安全性
2016/07/25 面试题
金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)-> (一千零一拾一元整)输出
2015/05/29 面试题
商业房地产广告语
2014/03/13 职场文书
优秀员工评优方案
2014/06/13 职场文书
关于群众路线的心得体会
2014/11/05 职场文书
2015年数学教研组工作总结
2015/05/23 职场文书