對於系統資源如文件、數據庫連接、socket 而言,應用程序打開這些資源並執行完業務邏輯之後,必須做的一件事就是要關閉(斷開)該資源。
比如 Python 程序打開一個文件,往文件中寫內容,寫完之後,就要關閉該文件,否則會出現什麼情況呢?極端情況下會出現 "Too many open files" 的錯誤,因爲系統允許你打開的最大文件數量是有限的。
同樣,對於數據庫,如果連接數過多而沒有及時關閉的話,就可能會出現 "Can not connect to MySQL server Too many connections",因爲數據庫連接是一種非常昂貴的資源,不可能無限制的被創建。
來看看如何正確關閉一個文件。
普通版:
def m1():
f = open("output.txt", "w")
f.write("人生苦短,我用python")
f.close()
這樣寫有一個潛在的問題,如果在調用 write 的過程中,出現了異常進而導致後續代碼無法繼續執行,close 方法無法被正常調用,因此資源就會一直被該程序佔用者釋放。那麼該如何改進代碼呢?
進階版:
def m2():
f = open("output.txt", "w")
try:
f.write("人生苦短,我用python")
except IOError:
print("oops error")
finally:
f.close()
改良版本的程序是對可能發生異常的代碼處進行 try 捕獲,使用 try/finally 語句,該語句表示如果在 try 代碼塊中程序出現了異常,後續代碼就不再執行,而直接跳轉到 except 代碼塊。而無論如何,finally 塊的代碼最終都會被執行。因此,只要把 close 放在 finally 代碼中,文件就一定會關閉。高級版:
def m3():
with open("output.txt", "r") as f:
f.write("人生苦短,我用python")
對於數據庫的操作也可以結合上下文管理器:
數據庫的操作分三步:
1.連接數據庫
2.sql執行語句
3.關閉連接
from pymysql import *
class DB(object):
def __init__(self, database_name, passward):
# 連接數據庫
self.conn = connect( host='localhost', port=3306, database= str(database_name), user='root', password=(passward),charset='utf8')
# 獲取cursor
self.cs1 =self.conn.cursor()
# self.sql = sql
# self.cs1.execute(self.sql)
def __enter__(self):
return self.cs1
def __exit__(self, *args):
self.cs1.close()
self.conn.close()
with DB('taobao', 'mysql') as f:
content = f.execute('select * from goods_brands')
t = f.fetchall()
print(t)