前言:本次實驗基于Python3.5丈屹,很多問題都是可以用debug調(diào)試出來的
Python 操作MySQL流程
1调俘、運行結(jié)果中文顯示亂碼
具體方法如下:
1)MySQL數(shù)據(jù)庫charset=utf-8
2)Python文件設(shè)置編碼 utf-8 ,在文件前面加上一下代碼
# -*- coding: utf-8 -*-
3)Python連接MySQL時加上參數(shù) charset=utf8
conn = pymysql.connect(host='localhost', port=3306, user='root',
passwd='123456', db='zyptest', charset='utf8')
4)設(shè)置Python的默認(rèn)編碼為 utf-8 (sys.setdefaultencoding(utf-8)
設(shè)置路徑:Pycharm軟件旺垒,F(xiàn)ile--Settings--File and Code Templates--Python Script
若想要結(jié)果以字典的方式輸出彩库,有2種方式(此方法不適用python3.6),代碼如下
- 在 connection 的地方加上 cursorclass = pymysql.cursors.DictCursor
conn = pymysql.connect(host='localhost', port=3306, user='root',
passwd='123456Aa', db='zyptest', charset='utf8',
cursorclass = pymysql.cursors.DictCursor)
- 創(chuàng)建游標(biāo)時指定
conn = pymysql.connect(host='localhost', port=3306, user='root',
passwd='123456Aa', db='zyptest', charset='utf8')
cur = conn.cursor(cursorclass=pymysql.cursors.DictCursor)
2先蒋、使用IP地址連接mysql數(shù)據(jù)庫服務(wù)時提示“1130-host 'LAPTOP OOR4C 1HG' is not allowed to connect to this MySql server”
(pymql.connection 使用 host 使用 localhost 表達(dá)時調(diào)試沒有問題)
解決辦法
(1)改表法侧巨。
可能是你的帳號不允許從遠(yuǎn)程登陸,只能在localhost
mysql> use mysql;
mysql> select host,user from user;
mysql> update user set host='%' where user='root' and host='localhost';
提醒:如果方法一解決不了你的問題鞭达,那還是先把user表中的host字段值改回去,再試試方法二
(2)授權(quán)法
Sql代碼(此處需要根據(jù)實際情況修改用戶(root)和密碼(123456)信息)
mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; //授權(quán)
mysql>flush privileges; //刷新權(quán)限皇忿,不需要重啟
3畴蹭、使用云服務(wù)器的IP地址連接mysql數(shù)據(jù)庫服務(wù)時提示“ConnectionRefusedError: [WinError 10061] 由于目標(biāo)計算機(jī)積極拒絕,無法連接鳍烁∵督螅”
原因分析:安裝mariadb時禁止了遠(yuǎn)程登錄
解決辦法:重新設(shè)置,允許遠(yuǎn)程登錄(詳情見之前安裝的文章)
1幔荒、找到mysql的配置文件my.cnf糊闽,使用命令 find / -name "*my.cnf"
2、在my.cnf文件的 [mysqld] 后加入skip-grant-tables爹梁,保存文件
3右犹、重啟mysql服務(wù) service mysql restart
4、重新登錄mysql (直接輸入mysql姚垃,不需要密碼)
5念链、修改密碼
use mysql;
update user set password=PASSWORD("密碼") where user='root';”(修改root的密碼)
6、再把配置文件的my.cnf 加入的skip-grant-tables刪除保存,或者 前面加上 #
7掂墓、重啟mysql服務(wù) (mysqld -restart)
8谦纱、重新登錄(使用密碼登錄,mysql -uroot -p)
4君编、運行正常跨嘉,但沒有結(jié)果輸出
OperationDbInterface 被封裝成了類,此時叫做方法吃嘿,想要調(diào)用的話需要實例化類祠乃。
(不封裝叫函數(shù))
if _name_ == "_main" (此處是2個下劃線)
在句子開始處加上if,就說明唠椭,這個句子是一個條件語句
_name_:作為模塊的內(nèi)置屬性,就是.py文件的調(diào)用方式
_main_:.py文件有兩種使用方式:作為模塊被調(diào)用和直接使用寺庄。如果它等于 "_main_" 就表示是直接執(zhí)行
在 if _name == "_main_" :之后的語句作為模塊被調(diào)用的時候斗塘,語句之后的代碼不執(zhí)行;直接使用的時候亮靴,語句之后的代碼執(zhí)行茧吊。通常搓侄,此語句用于模塊測試中使用讶踪。
貼上源代碼
import pymysql
import os
import logging
class OperationDbInterface(object): # 聲明類
def __init__(self):
self.conn = pymysql.connect(host='localhost', port=3306, user='root',
passwd='123456', db='mysql', charset='utf8')
self.cur = self.conn.curror() # 創(chuàng)建游標(biāo)
# 定義單條數(shù)據(jù)操作乳讥,增刪改
def op_sql(self, param):
try:
self.cur.execute(param) # 執(zhí)行sql語句
self.conn.commit()
return True
except pymysql.Error as e:
print("Mysql Error %d: %s" % (e.args[0], e.args[1]))
logging.basicConfig(filename=os.path.join(os.getcwd(), './log.txt'),
level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] % (levelname)s %(message)s')
logger = logging.getLogger(__name__)
logger.exception(e)
return False
# 查詢表中單條數(shù)據(jù)
def selectone(self, condition):
try:
self.cur.execute(condition)
results = self.cur.fetchone() # 獲取一條數(shù)據(jù)
except pymysql.Error as e:
results = 'sql0001' # 數(shù)據(jù)庫執(zhí)行錯誤
print("Mysql Error %d: %s" % (e.args[0], e.args[1]))
logging.basicConfig(filename=os.path.join(os.getcwd(), './log.txt'),
level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] % (levelname)s %(message)s')
logger = logging.getLogger(__name__)
logger.exception(e)
finally:
return results
# 查詢表中多條數(shù)據(jù)
def selectall(self, conditon):
try:
self.cur.execute(conditon)
self.cur.scroll(0, mode='absolute') # 光標(biāo)回到初始位置
results = self.cur.fetchall() # 返回游標(biāo)中所有結(jié)果
except pymysql.Error as e:
results = 'sql0001' # 數(shù)據(jù)庫執(zhí)行錯誤
print("Mysql Error %d: %s" % (e.args[0], e.args[1]))
logging.basicConfig(filename=os.path.join(os.getcwd(), './log.txt'),
level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
logger = logging.getLogger(__name__)
logger.exception(e)
finally:
return results
# 定義表中插入多條數(shù)據(jù)操作
def insertmore(self, condition):
try:
self.cur.executemany(condition)
self.conn.commit()
return True
except pymysql.Error as e:
results = 'sql0001' # 數(shù)據(jù)庫執(zhí)行錯誤
print("Mysql Error %d: %s" % (e.args[0], e.args[1]))
logging.basicConfig(filename=os.path.join(os.getcwd(), './log.txt'),
level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
logger = logging.getLogger(__name__)
logger.exception(e)
return False
# 判斷表是否存在
def __del__(self):
if self.cur is not None:
self.cur.close()
if self.conn is not None:
self.conn.close()
if __name__ == '__main()__':
test = OperationDbInterface() # 實例化類
result = test.selectone('select * from db')
print(result)
原因分析:main()多了括號汹忠,應(yīng)該是
if __name__ == '__main__':
改完之后運行報錯 “AttributeError: 'Connection' object has no attribute 'curror'”
根據(jù)錯誤提醒回到20行代碼檢查,發(fā)現(xiàn)是 cursor 拼錯了
接著改好執(zhí)行發(fā)現(xiàn)結(jié)果出來了橄唬,但是仍有報錯信息(Python3.5正常沒有報錯仰楚,如下圖是3.6的報錯信息)
備注:待解決
5、執(zhí)行錯誤語句臭挽,生成日志文件欢峰,打開沒有內(nèi)容
檢查發(fā)現(xiàn) logging 用的是2.7的語法格式宠漩,用2.7調(diào)試報錯
6扒吁、執(zhí)行插入語句時報錯
TypeError: insertmore() takes 2 positional arguments but 3 were given
原因分析:
executemany()方法是要傳兩個參數(shù),一個sql語句一個args(list)盼铁,源碼中只有一個參數(shù)
解決辦法:函數(shù)中增加參數(shù) params
7、執(zhí)行批量刪除語句時報錯
def deletemore(self, condition, params):
try:
self.cur.executemany(condition, params) # executemany為批量操作冬念,可以進(jìn)行多行插入
self.conn.commit()
return True
if __name__ == "__main__":
test = OperationDbInterface() # 實例化類
result = test.deletemore("delete from student WHERE id in(6,7)")
print(result)
原因分析:不管字段是str,還是int裆针,或者其他類型世吨,都需要使用 %s 傳遞參數(shù)的方式進(jìn)行耘婚,正確如下
result = test.deletemore("delete from student WHERE id in(%s)",[6,7])