高級python程序設計,python(三)之高級篇

 2023-11-07 阅读 29 评论 0

摘要:python之高級篇一、文件操作二、讀寫文本文件三、讀寫二進制文件四、讀寫JSON文件五、異常詳解六、進程和線程七、單進程與多進程八、多線程編程九、多進程還是多線程十、requests 庫十一、數據庫操作 一、文件操作 高級python程序設計。??在實際開發中,常常需要對程序

python之高級篇

  • 一、文件操作
  • 二、讀寫文本文件
  • 三、讀寫二進制文件
  • 四、讀寫JSON文件
  • 五、異常詳解
  • 六、進程和線程
  • 七、單進程與多進程
  • 八、多線程編程
  • 九、多進程還是多線程
  • 十、requests 庫
  • 十一、數據庫操作

一、文件操作

高級python程序設計。??在實際開發中,常常需要對程序中的數據進行持久化操作,而實現數據持久化最直接簡單的方式就是將數據保存到文件中。在Python中實現文件的讀寫操作其實非常簡單,通過Python內置的open函數,我們可以指定文件名、操作模式、編碼信息等來獲得操作文件的對象,接下來就可以對文件進行讀寫操作了。這里所說的操作模式是指要打開什么樣的文件(字符文件還是二進制文件)以及做什么樣的操作(讀、寫還是追加),具體的如下表所示。

操作模式	具體含義
'r'        	讀取 (默認)
'w'	        寫入(會先截斷之前的內容)
'x'	        寫入,如果文件已經存在會產生異常
'a'	        追加,將內容寫入到已有文件的末尾
'b'	        二進制模式
't'	        文本模式(默認)
'+'	        更新(既可以讀又可以寫)

??通過encoding參數指定編碼(如果不指定,默認值是None,那么在讀取文件時使用的是操作系統默認的編碼),如果不能保證保存文件時使用的編碼方式與encoding參數指定的編碼方式是一致的,那么就可能因無法解碼字符而導致讀取失敗。

f = open('c://user.sql', 'r', encoding='utf-8')

二、讀寫文本文件

??讀取文本文件時,需要在使用open函數時指定好帶路徑的文件名(可以使用相對路徑或絕對路徑)并將文件模式設置為’r’(如果不指定,默認值也是’r’),下面的例子演示了如何讀取一個純文本文件。

def main():f = open('c://user.sql', 'r', encoding='utf-8')print(f.read())f.close()
if __name__ == '__main__':main()

python高階函數。??請注意上面的代碼,如果open函數指定的文件并不存在或者無法打開,那么將引發異常狀況導致程序崩潰。為了讓代碼有一定的健壯性和容錯性,我們可以使用Python的異常機制對可能在運行時發生狀況的代碼進行適當的處理,如下所示。

def main():f = Nonetry:f = open('c://user.sql', 'r', encoding='utf-8')print(f.read())except FileNotFoundError:print('無法打開指定的文件!')except LookupError:print('指定了未知的編碼!')except UnicodeDecodeError:print('讀取文件時解碼錯誤!')finally:if f:f.close()
if __name__ == '__main__':main()

??在 Python 中,我們可以將那些在運行時可能會出現狀況的代碼放在 try 代碼塊中,在try代碼塊的后面可以跟上一個或多個except來捕獲可能出現的異常狀況。例如在上面讀取文件的過程中,文件找不到會引發FileNotFoundError,指定了未知的編碼會引發LookupError,而如果讀取文件時無法按指定方式解碼會引發UnicodeDecodeError,我們在try后面跟上了三個except分別處理這三種不同的異常狀況。最后我們使用finally代碼塊來關閉打開的文件,釋放掉程序中獲取的外部資源,由于finally塊的代碼不論程序正常還是異常都會執行到,因此我們通常把finally塊稱為“總是執行代碼塊”,它最適合用來做釋放外部資源的操作。

??除了使用文件對象的read方法讀取文件之外,還可以使用for-in循環逐行讀取或者用readlines方法將文件按行讀取到一個列表容器中,代碼如下所示。

import timedef main():# 通過for-in循環逐行讀取f = open('c://user.sql', 'r', encoding='utf-8')for line in f:print(line, end='')time.sleep(0.5)print()# 讀取文件按行讀取到列表中f = open('c://user.sql', 'r', encoding='utf-8')lines = f.readlines()print(lines)f.close()if __name__ == '__main__':main()

python和c。??要將文本信息寫入文件文件也非常簡單,在使用 open 函數時指定好文件名并將文件模式設置為’w’即可。注意如果需要對文件內容進行追加式寫入,應該將模式設置為’a’。如果要寫入的文件不存在會自動創建文件而不是引發異常。

def main():# 寫入f = open('c://aa.txt', 'w', encoding='utf-8')f.write("123456")f.close()# 追加f = open("c://aa.txt", 'a', encoding='utf-8')f.write("78910j")f.close()if __name__ == '__main__':main()

三、讀寫二進制文件

??知道了如何讀寫文本文件要讀寫二進制文件也就很簡單了,下面的代碼實現了復制圖片文件的功能。

def main():fs1 = open('c://aa.png', 'rb')data = fs1.read()print(type(data))  # <class 'bytes'>fs2 = open('c://bb.png', 'wb')fs2.write(data)print('程序執行結束.')if __name__ == '__main__':main()

四、讀寫JSON文件

??如果希望把一個列表或者一個字典中的數據保存到文件中又該怎么做呢?答案是將數據以JSON格式進行保存。JSON是“JavaScript Object Notation”的縮寫,它本來是JavaScript語言中創建對象的一種字面量語法,現在已經被廣泛的應用于跨平臺跨語言的數據交換,原因很簡單,因為JSON也是純文本,任何系統任何編程語言處理純文本都是沒有問題的。目前JSON基本上已經取代了XML作為異構系統間交換數據的事實標準。關于JSON的知識,更多的可以參考JSON的官方網站,從這個網站也可以了解到每種語言處理JSON數據格式可以使用的工具或三方庫,下面是一個JSON的簡單例子。

{"id":12,"name": "張三","age": 38,"friends": ["王大錘", "白元芳"],"role": {"id":2,"roleName":"超級管理員"}
}

python爬蟲教程,我們使用Python中的json模塊就可以將字典或列表以JSON格式保存到文件中,代碼如下所示。

import jsondef main():data = {"id": 12,"name": "張三","age": 38,"friends": ["王大錘", "白元芳"],"role": {"id": 2,"roleName": "超級管理員"}}fs = open('data.json', 'w', encoding='utf-8')json.dump(data, fs)    print('保存數據完成!')if __name__ == '__main__':main()

json 模塊主要有四個比較重要的函數,分別是:

??* dump - 將Python對象按照JSON格式序列化到文件中
??* dumps - 將Python對象處理成JSON格式的字符串
??* load - 將文件中的JSON數據反序列化成對象
??* loads - 將字符串的內容反序列化成Python對象

python編程、??這里出現了兩個概念,一個叫序列化,一個叫反序列化。自由的百科全書維基百科上對這兩個概念是這樣解釋的:“序列化(serialization)在計算機科學的數據處理中,是指將數據結構或對象狀態轉換為可以存儲或傳輸的形式,這樣在需要的時候能夠恢復到原先的狀態,而且通過序列化的數據重新獲取字節時,可以利用這些字節來產生原始對象的副本(拷貝)。與這個過程相反的動作,即從一系列字節中提取數據結構的操作,就是反序列化(deserialization)”。

import jsondef main():fs = open('data.json', 'r', encoding='utf-8')data = json.load(fs)print(data)if __name__ == '__main__':main()

五、異常詳解

??異常處理在任何一門編程語言里都是值得關注的一個話題,良好的異常處理可以讓你的程序更加健壯,清晰的錯誤信息更能幫助你快速修復問題。在Python中,和不部分高級語言一樣,使用了try/except/finally 語句塊來處理異常,如果你有其他編程語言的經驗,實踐起來并不難。

??在可能發生異常的位置使用 try/except/finally 來控制程序出現異常后的操作,而不是程序崩潰并結束。

def main():f = Nonetry:f = open('致橡樹.txt', 'r', encoding='utf-8')print(f.read())except FileNotFoundError:print('無法打開指定的文件!')except LookupError:print('指定了未知的編碼!')except UnicodeDecodeError:print('讀取文件時解碼錯誤!')finally:if f:f.close()
if __name__ == '__main__':main()

??如果不愿意在 finally 代碼塊中關閉文件對象釋放資源,也可以使用上下文語法,通過 with 關鍵字指定文件對象的上下文環境并在離開上下文環境時自動釋放文件資源,代碼如下所示。

def main():try:with open('致橡樹.txt', 'r', encoding='utf-8') as f:print(f.read())except FileNotFoundError:print('無法打開指定的文件!')except LookupError:print('指定了未知的編碼!')except UnicodeDecodeError:print('讀取文件時解碼錯誤!')
if __name__ == '__main__':main()

例如上面json文件讀取的代碼可以改寫為:

import jsondef main():try:with open('data.json', 'r', encoding='utf-8') as fs:data = json.load(fs)print(data)except IOError as e:print(e)if __name__ == '__main__':main()

六、進程和線程

??今天我們使用的計算機早已進入多CPU或多核時代,而我們使用的操作系統都是支持“多任務”的操作系統,這使得我們可以同時運行多個程序,也可以將一個程序分解為若干個相對獨立的子任務,讓多個子任務并發的執行,從而縮短程序的執行時間,同時也讓用戶獲得更好的體驗。因此在當下不管是用什么編程語言進行開發,實現讓程序同時執行多個任務也就是常說的“并發編程”,應該是程序員必備技能之一。為此,我們需要先討論兩個概念,一個叫進程,一個叫線程。

??進程就是操作系統中執行的一個程序,操作系統以進程為單位分配存儲空間,每個進程都有自己的地址空間、數據棧以及其他用于跟蹤進程執行的輔助數據,操作系統管理所有進程的執行,為它們合理的分配資源。進程可以通過fork或spawn的方式來創建新的進程來執行其他的任務,不過新的進程也有自己獨立的內存空間,因此必須通過進程間通信機制(IPC,Inter-Process Communication)來實現數據共享,具體的方式包括管道、信號、套接字、共享內存區等。

??一個進程還可以擁有多個并發的執行線索,簡單的說就是擁有多個可以獲得CPU調度的執行單元,這就是所謂的線程。由于線程在同一個進程下,它們可以共享相同的上下文,因此相對于進程而言,線程間的信息共享和通信更加容易。當然在單核CPU系統中,真正的并發是不可能的,因為在某個時刻能夠獲得CPU的只有唯一的一個線程,多個線程共享了CPU的執行時間。使用多線程實現并發編程為程序帶來的好處是不言而喻的,最主要的體現在提升程序的性能和改善用戶體驗,今天我們使用的軟件幾乎都用到了多線程技術,這一點可以利用系統自帶的進程監控工具(如macOS中的“活動監視器”、Windows中的“任務管理器”)來證實,如下圖所示。
在這里插入圖片描述
??當然多線程也并不是沒有壞處,站在其他進程的角度,多線程的程序對其他程序并不友好,因為它占用了更多的CPU執行時間,導致其他程序無法獲得足夠的CPU執行時間;另一方面,站在開發者的角度,編寫和調試多線程的程序都對開發者有較高的要求,對于初學者來說更加困難。

??Python既支持多進程又支持多線程,因此使用Python實現并發編程主要有3種方式:多進程、多線程、多進程+多線程。

七、單進程與多進程

??下面用一個下載文件的例子來說明使用多進程和不使用多進程到底有什么差別,先看看下面的代碼。

from random import randint
from time import time, sleepdef download_task(filename):print('開始下載%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main():start = time()download_task('Python從入門到住院.pdf')download_task('Peking Hot.avi')end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__':main()

??從上面的例子可以看出,如果程序中的代碼只能按順序一點點的往下執行,那么即使執行兩個毫不相關的下載任務,也需要先等待一個文件下載完成后才能開始下一個下載任務,很顯然這并不合理也沒有效率。接下來我們使用多進程的方式將兩個下載任務放到不同的進程中,代碼如下所示。

from multiprocessing import Process
from os import getpid
from random import randint
from time import time, sleepdef download_task(filename):print('啟動下載進程,進程號[%d].' % getpid())print('開始下載%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main():start = time()p1 = Process(target=download_task, args=('Python從入門到住院.pdf',))p1.start()p2 = Process(target=download_task, args=('Peking Hot.avi',))p2.start()p1.join()p2.join()end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__':main()

??在上面的代碼中,我們通過Process類創建了進程對象,通過target參數我們傳入一個函數來表示進程啟動后要執行的代碼,后面的args是一個元組,它代表了傳遞給函數的參數。Process對象的start方法用來啟動進程,而join方法表示等待進程執行結束。運行上面的代碼可以明顯發現兩個下載任務“同時”啟動了,而且程序的執行時間將大大縮短,不再是兩個任務的時間總和。

八、多線程編程

??在Python早期的版本中就引入了thread模塊(現在名為_thread)來實現多線程編程,然而該模塊過于底層,而且很多功能都沒有提供,因此目前的多線程開發我們推薦使用threading模塊,該模塊對多線程編程提供了更好的面向對象的封裝。我們把剛才下載文件的例子用多線程的方式來實現一遍。

from random import randint
from threading import Thread
from time import time, sleepdef download(filename):print('開始下載%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main():start = time()t1 = Thread(target=download, args=('Python從入門到住院.pdf',))t1.start()t2 = Thread(target=download, args=('Peking Hot.avi',))t2.start()t1.join()t2.join()end = time()print('總共耗費了%.3f秒' % (end - start))if __name__ == '__main__':main()

??我們可以直接使用threading模塊的Thread類來創建線程,但是我們之前講過一個非常重要的概念叫“繼承”,我們可以從已有的類創建新類,因此也可以通過繼承Thread類的方式來創建自定義的線程類,然后再創建線程對象并啟動線程。代碼如下所示。

from random import randint
from threading import Thread
from time import time, sleepclass DownloadTask(Thread):def __init__(self, filename):super().__init__()self._filename = filenamedef run(self):print('開始下載%s...' % self._filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (self._filename, time_to_download))def main():start = time()t1 = DownloadTask('Python從入門到住院.pdf')t1.start()t2 = DownloadTask('Peking Hot.avi')t2.start()t1.join()t2.join()end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__':main()

??因為多個線程可以共享進程的內存空間,因此要實現多個線程間的通信相對簡單,大家能想到的最直接的辦法就是設置一個全局變量,多個線程共享這個全局變量即可。但是當多個線程共享同一個變量(我們通常稱之為“資源”)的時候,很有可能產生不可控的結果從而導致程序失效甚至崩潰。如果一個資源被多個線程競爭使用,那么我們通常稱之為“臨界資源”,對“臨界資源”的訪問需要加上保護,否則資源會處于“混亂”的狀態。下面的例子演示了100個線程向同一個銀行賬戶轉賬(轉入1元錢)的場景,在這個例子中,銀行賬戶就是一個臨界資源,在沒有保護的情況下我們很有可能會得到錯誤的結果。

from time import sleep
from threading import Threadclass Account(object):def __init__(self):self._balance = 0def deposit(self, money):# 計算存款后的余額new_balance = self._balance + money# 模擬受理存款業務需要0.01秒的時間sleep(0.01)# 修改賬戶余額self._balance = new_balance@propertydef balance(self):return self._balanceclass AddMoneyThread(Thread):def __init__(self, account, money):super().__init__()self._account = accountself._money = moneydef run(self):self._account.deposit(self._money)def main():account = Account()threads = []# 創建100個存款的線程向同一個賬戶中存錢for _ in range(100):t = AddMoneyThread(account, 1)threads.append(t)t.start()# 等所有存款的線程都執行完畢for t in threads:t.join()print('賬戶余額為: ¥%d元' % account.balance)if __name__ == '__main__':main()

??運行上面的程序,結果讓人大跌眼鏡,100個線程分別向賬戶中轉入1元錢,結果居然遠遠小于100元。之所以出現這種情況是因為我們沒有對銀行賬戶這個“臨界資源”加以保護,多個線程同時向賬戶中存錢時,會一起執行到new_balance = self._balance + money這行代碼,多個線程得到的賬戶余額都是初始狀態下的0,所以都是0上面做了+1的操作,因此得到了錯誤的結果。在這種情況下,“鎖”就可以派上用場了。我們可以通過“鎖”來保護“臨界資源”,只有獲得“鎖”的線程才能訪問“臨界資源”,而其他沒有得到“鎖”的線程只能被阻塞起來,直到獲得“鎖”的線程釋放了“鎖”,其他線程才有機會獲得“鎖”,進而訪問被保護的“臨界資源”。下面的代碼演示了如何使用“鎖”來保護對銀行賬戶的操作,從而獲得正確的結果。

from time import sleep
from threading import Thread, Lockclass Account(object):def __init__(self):self._balance = 0self._lock = Lock()def deposit(self, money):# 先獲取鎖才能執行后續的代碼self._lock.acquire()try:new_balance = self._balance + moneysleep(0.01)self._balance = new_balancefinally:# 在finally中執行釋放鎖的操作保證正常異常鎖都能釋放self._lock.release()@propertydef balance(self):return self._balance
class AddMoneyThread(Thread):def __init__(self, account, money):super().__init__()self._account = accountself._money = moneydef run(self):self._account.deposit(self._money)
def main():account = Account()threads = []# 創建100個存款的線程向同一個賬戶中存錢for _ in range(100):t = AddMoneyThread(account, 1)threads.append(t)t.start()# 等所有存款的線程都執行完畢for t in threads:t.join()print('賬戶余額為: ¥%d元' % account.balance)
if __name__ == '__main__':main()

??比較遺憾的一件事情是Python的多線程并不能發揮CPU的多核特性,這一點只要啟動幾個執行死循環的線程就可以得到證實了。之所以如此,是因為Python的解釋器有一個“全局解釋器鎖”(GIL)的東西,任何線程執行前必須先獲得GIL鎖,然后每執行100條字節碼,解釋器就自動釋放GIL鎖,讓別的線程有機會執行,這是一個歷史遺留問題,但是即便如此,就如我們之前舉的例子,使用多線程在提升執行效率和改善用戶體驗方面仍然是有積極意義的。

九、多進程還是多線程

??無論是多進程還是多線程,只要數量一多,效率肯定上不去,為什么呢?我們打個比方,假設你不幸正在準備中考,每天晚上需要做語文、數學、英語、物理、化學這5科的作業,每項作業耗時1小時。如果你先花1小時做語文作業,做完了,再花1小時做數學作業,這樣,依次全部做完,一共花5小時,這種方式稱為單任務模型。如果你打算切換到多任務模型,可以先做1分鐘語文,再切換到數學作業,做1分鐘,再切換到英語,以此類推,只要切換速度足夠快,這種方式就和單核CPU執行多任務是一樣的了,以旁觀者的角度來看,你就正在同時寫5科作業。

??但是,切換作業是有代價的,比如從語文切到數學,要先收拾桌子上的語文書本、鋼筆(這叫保存現場),然后,打開數學課本、找出圓規直尺(這叫準備新環境),才能開始做數學作業。操作系統在切換進程或者線程時也是一樣的,它需要先保存當前執行的現場環境(CPU寄存器狀態、內存頁等),然后,把新任務的執行環境準備好(恢復上次的寄存器狀態,切換內存頁等),才能開始執行。這個切換過程雖然很快,但是也需要耗費時間。如果有幾千個任務同時進行,操作系統可能就主要忙著切換任務,根本沒有多少時間去執行任務了,這種情況最常見的就是硬盤狂響,點窗口無反應,系統處于假死狀態。所以,多任務一旦多到一個限度,反而會使得系統性能急劇下降,最終導致所有任務都做不好。

??是否采用多任務的第二個考慮是任務的類型,可以把任務分為計算密集型和I/O密集型。計算密集型任務的特點是要進行大量的計算,消耗CPU資源,比如對視頻進行編碼解碼或者格式轉換等等,這種任務全靠CPU的運算能力,雖然也可以用多任務完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低。計算密集型任務由于主要消耗CPU資源,這類任務用Python這樣的腳本語言去執行效率通常很低,最能勝任這類任務的是C語言,我們之前提到了Python中有嵌入C/C++代碼的機制。

??除了計算密集型任務,其他的涉及到網絡、存儲介質I/O的任務都可以視為I/O密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待I/O操作完成(因為I/O的速度遠遠低于CPU和內存的速度)。對于I/O密集型任務,如果啟動多任務,就可以減少I/O等待時間從而讓CPU高效率的運轉。有一大類的任務都屬于I/O密集型任務,這其中包括了我們很快會涉及到的網絡應用和Web應用。

十、requests 庫

??HTTP 是超文本傳輸協議(Hyper-Text Transfer Proctol)的簡稱,維基百科上對HTTP的解釋是:超文本傳輸協議是一種用于分布式、協作式和超媒體信息系統的應用層協議,它是萬維網數據通信的基礎,設計HTTP最初的目的是為了提供一種發布和接收HTML頁面的方法,通過HTTP或者HTTPS(超文本傳輸安全協議)請求的資源由URI(統一資源標識符)來標識。requests 是一個基于HTTP協議來使用網絡的第三庫,其官方網站有這樣的一句介紹它的話:“Requests是唯一的一個非轉基因的Python HTTP庫,人類可以安全享用。”簡單的說,使用requests庫可以非常方便的使用HTTP,避免安全缺陷、冗余代碼以及“重復發明輪子”。下面我們還是通過requests來實現一個訪問網絡數據接口并從中獲取美女圖片下載鏈接然后下載美女圖片到本地的例子程序,程序中使用了天行數據提供的網絡API。

??我們可以先通過pip安裝requests及其依賴庫。

pip install requests

然后通過 pip list 命令查看是否安裝成功。

C:\Users\Administrator>pip list
Package    Version
---------- ---------
certifi    2020.12.5
chardet    4.0.0
idna       2.10
pip        21.0.1
requests   2.25.1
setuptools 47.1.0
urllib3    1.26.3

使用

from threading import Thread
import requests# 繼承Thread類創建自定義的線程類
class DownloadHanlder(Thread):def __init__(self, url):super().__init__()self.url = urldef run(self):filename = self.url[self.url.rfind('/') + 1:]resp = requests.get(self.url)with open('c://' + filename, 'wb') as f:f.write(resp.content)
def main():# 通過requests模塊的post函數獲取網絡json資源resp = requests.post('http://58.42.239.163:8888/jwxt/findPublicNoteBook')# 將服務器返回的JSON格式的數據解析為字典data_model = resp.json()print(data_model)for mm_dict in data_model['obj']:url = mm_dict['img']# 通過多線程的方式實現圖片下載DownloadHanlder("http://58.42.239.163:8888/static/" + url).start()
if __name__ == '__main__':main()

十一、數據庫操作

??在 Python 3中,我們通常使用純 Python 的三方庫 PyMySQL 來訪問 MySQL 數據庫,它應該是目前 Python 操作 MySQL 數據庫最好的選擇。使用 PyMySQL 前需要安裝 PyMySQL,然后就可以使用 PyMySQL 進行數據庫的增刪改查操作。

pip install pymysql

數據準備:

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL,`password` varchar(50) NOT NULL,`telephone` varchar(11) NOT NULL,`email` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
insert  into `user`(`id`,`name`,`password`,`telephone`,`email`) values (1,'張三','123456','15902698148','123@qq.com');

添加數據:

import pymysqldef main():name = input('姓名: ')password = input('密碼: ')telephone = input('電話: ')email = input('郵箱: ')# 1. 創建數據庫連接對象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456')try:# 2. 通過連接對象獲取游標with con.cursor() as cursor:# 3. 通過游標執行SQL并獲得執行結果result = cursor.execute('insert into user(name,password,telephone,email) values (%s, %s, %s, %s)',(name, password, telephone, email))if result == 1:print('添加成功!')# 4. 操作成功提交事務con.commit()finally:# 5. 關閉連接釋放資源con.close()if __name__ == '__main__':main()

修改數據:

??其實在大部分的編程語言中操作數據庫都只有兩類操作,及查詢和更新。修改數據的操作和添加基本相同,刪除也是類似的。

??注意:如果不希望每次 SQL 操作之后手動提交或回滾事務,可以像下面的代碼那樣,在創建連接的時候多加一個名為 autocommit 的參數并將它的值設置為 True,表示每次執行 SQL 之后自動提交。如果程序中不需要使用事務環境也不希望手動的提交或回滾就可以這么做。

import pymysqldef main():data_id = int(input('ID: '))name = input('姓名: ')password = input('密碼: ')telephone = input('電話: ')email = input('郵箱: ')# 1. 創建數據庫連接對象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456', autocommit=True)try:# 2. 通過連接對象獲取游標with con.cursor() as cursor:# 3. 通過游標執行SQL并獲得執行結果result = cursor.execute('update user set name =%s,password =%s,telephone =%s,email =%s where id =%s',(name, password, telephone, email, data_id))if result == 1:print('添加成功!')finally:# 5. 關閉連接釋放資源con.close()if __name__ == '__main__':main()

查詢數據:

??在 Python 中調用游標的 fetchall 即可獲取全部的結果集合,集合中的每個元素都是標準的 json 對象。如果查詢的結果確定為一條時使用 fetchone 會將結果封裝成 json 對象。

import pymysql
from pymysql.cursors import DictCursordef main():# 1. 創建數據庫連接對象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456')try:with con.cursor(cursor=DictCursor) as cursor:cursor.execute('select * from user')results = cursor.fetchall()print(results)print('id\tname\tpassword\ttelephone\temail')for dept in results:print(dept['id'], end='\t')print(dept['name'], end='\t')print(dept['password'], end='\t')print(dept['telephone'], end='\t')print(dept['email'])finally:con.close()if __name__ == '__main__':main()

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/169861.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息