首页 > 技术文章 > Python3 --pymysql模块

yunlong-study 2021-02-23 14:42 原文

一. 安装

#安装
pip3 install pymysql
PyMySQL 安装
在使用 PyMySQL 之前,我们需要确保 PyMySQL 已安装。

PyMySQL 下载地址:https://github.com/PyMySQL/PyMySQL。

如果还未安装,我们可以使用以下命令安装最新版的 PyMySQL:

$ pip3 install PyMySQL
如果你的系统不支持 pip 命令,可以使用以下方式安装:

1、使用 git 命令下载安装包安装(你也可以手动下载):

$ git clone https://github.com/PyMySQL/PyMySQL
$ cd PyMySQL/
$ python3 setup.py install
2、如果需要制定版本号,可以使用 curl 命令来安装:

$ # X.X 为 PyMySQL 的版本号
$ curl -L https://github.com/PyMySQL/PyMySQL/tarball/pymysql-X.X | tar xz
$ cd PyMySQL*
$ python3 setup.py install
$ # 现在你可以删除 PyMySQL* 目录
注意:请确保您有root权限来安装上述模块。

安装的过程中可能会出现"ImportError: No module named setuptools"的错误提示,意思是你没有安装setuptools,你可以访问https://pypi.python.org/pypi/setuptools 找到各个系统的安装方法。

Linux 系统安装实例:

$ wget https://bootstrap.pypa.io/ez_setup.py
$ python3 ez_setup.py
PyMySQL 安装(详细)

 

一 链接、执行sql、关闭(游标)

import pymysql
user=input('用户名: ').strip()
pwd=input('密码: ').strip()

#连接数据库
conn=pymysql.connect(host='localhost',user=user,password=pwd,database='egon',charset='utf8')
#使用cursor()方法创建一个游标对象
cursor=conn.cursor() #执行完毕返回的结果集默认以元组显示
#cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)#cursor其实是调用了cursors模块下的Cursor的类,这个模块主要的作用就是用来和数据库交互的


#执行sql语句,使用execute()方法执行SQL语句
sql='select * from userinfo where name="%s" and password="%s"' %(user,pwd) #注意%s需要加引号
print(sql)
res=cursor.execute(sql) #执行sql语句,返回sql查询成功的记录数目
print(res)

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

#关闭游标和数据库的连接
cursor.close()
conn.
close()
if res: print('登录成功') else: print('登录失败')

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)

参数
conect中的参数
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"""
    ......
cursor的一些绑定方法

 

二.SQL注入(execute()之下)

原因详解请看:https://www.cnblogs.com/yunlong-study/p/14435609.html 

用户名: 123" or 1=1 -- sdada
密码: 
select * from t3 where class="123" or 1=1 -- sdada" and name=""
1
登录成功
# 原来是我们对sql进行字符串拼接
# sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd)
# print(sql)
# res=cursor.execute(sql)

#改写为(execute帮我们做字符串拼接,我们无需且一定不能再为%s加引号了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s需要去掉引号,因为pymysql会自动为我们加上
res=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮我们解决sql注入的问题,只要我们按照pymysql的规矩来。

 

三. 增、删、改:conn.commit()

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

import pymysql
config={
    "host":"127.0.0.1",
    "user":"root",
    "password":"123456",
    "database":"yun"
}
db = pymysql.connect(**config)
cursor = db.cursor()
sql = "INSERT INTO userinfo(username,passwd) VALUES('jack','123')"
cursor.execute(sql)

#
或者在execute提供插入的数据
#sql = "INSERT INTO userinfo(username,passwd) VALUES(%s,%s)"
#cursor.execute(sql,("bob","123"))  #传进去的值会被转成str
db.commit() #提交数据 
cursor.close()
db.close()

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()
executemany

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

当表中有自增的主键的时候,可以使用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
lastrowid

 

四. 查:fetchone,fetchmany,fetchall

fetchone():获取下一行数据,第一次为首行;
fetchall():获取所有行数据源
fetchmany(4):获取4行数据
import pymysql
config={
    "host":"127.0.0.1",
    "user":"root",
    "password":"123456",
    "database":"yun"
}
db = pymysql.connect(**config)
cursor = db.cursor()
#sql = "INSERT INTO t3 VALUES('jack',2,'jack',30,40)"
sql = 'select * from t3'
res = cursor.execute(sql)
print(res)
data = cursor.fetchone()
print(data)
data = cursor.fetchone()#没执行一次,往后挪一位
print(data)

cursor.close()
db.close()
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.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'))
()
fetchall

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

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

cursor = db.cursor(cursor=pymysql.cursors.DictCursor)  #在实例化的时候,将属性cursor设置为pymysql.cursors.DictCursor
import pymysql
config={
    "host":"127.0.0.1",
    "user":"root",
    "password":"123456",
    "database":"yun"
}
db = pymysql.connect(**config)
cursor = db.cursor(cursor=pymysql.cursors.DictCursor)
#sql = "INSERT INTO t3 VALUES('jack',2,'jack',30,40)"
sql = 'select * from t3'
res = cursor.execute(sql)
print(res)
data = cursor.fetchone()
print(data)
data = cursor.fetchone()
print(data)

cursor.close()
db.close()

'''
结果:
4
{'class': 'jsj', 'id': 2, 'name': 'long', 'score': 0, 'age': 20}
{'class': 'jack', 'id': 2, 'name': 'jack', 'score': 30, 'age': 40}
'''
返回结果是字典

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

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

cursor.scroll(1,mode='relative')  # 相对当前位置移动
cursor.scroll(2,mode='absolute') # 相对绝对位置移动
第一个值为移动的行数,整数为向下移动,负数为向上移动,mode指定了是相对当前位置移动,还是相对于首行移动
sql = 'select * from t3'
res = cursor.execute(sql)
print(res)
data = cursor.fetchall()
print(data)
cursor.scroll(0,mode='absolute')
data = cursor.fetchone()
print(data)
[{'class': 'jsj', 'id': 2, 'name': 'long', 'score': 0, 'age': 20}, {'class': 'jack', 'id': 2, 'name': 'jack', 'score': 30, 'age': 40}, {'class': 'jack', 'id': 2, 'name': 'jack', 'score': 30, 'age': 40}, {'class': 'jack', 'id': 2, 'name': 'jack', 'score': 30, 'age': 50}]
{'class': 'jsj', 'id': 2, 'name': 'long', 'score': 0, 'age': 20}
结果

 

五. 上下文管理器

在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'}
with

 

 

摘自:https://www.cnblogs.com/liubinsh/p/7568423.html

https://zhuanlan.zhihu.com/p/115504709

 

推荐阅读