写程序就会用到数据库,用到数据库就会用到对应的driver,调用这些driver操作数据库的时候难免就会出问题,为了避免程序挂掉,捕捉driver报出的异常,记录日志就很有必要。
pymongo是MongoDB的python driver,用python操作MongoDB的时候就会用到它,当你连接数据库所使用的一些配置文件里的参数有问题,例如IP/Port错了,pymongo自然就连不上数据库,如果你已经用习惯了 try/except,你可能就会写这样的代码出来——
from pymongo import MongoClient
import pymongo.errors
import json
class DbConnector:
def __init__(self):
with open(file="config.json", mode="r", encoding="utf-8") as self.dbinfo:
self.dbinfo = json.load(self.dbinfo)
client = MongoClient("mongodb://{}/".format(self.dbinfo["DB"]["hostlist"]))
self.db = client[self.dbinfo["DB"]["dbName"]]
P.S. 我把数据库的信息存在了config.json,之所以存成json,是因为……嗯……因为json这个模块用的比较熟……(捂脸)
上面的示例还没有加入异常的捕获,想当然的去写的话,会写成这样……
try:
client = MongoClient("mongodb://{}/".format(self.dbinfo["DB"]["hostlist"]))
except pymongo.errors.PyMongoError as e:
print("DB ERROR!")
P.S. except 语句后接的 print 只是一个示例,实际的代码中,你应该调用log模块,或者自己定义异常类然后引发它,再到程序外部捕捉后处理,此处不赘述
但是,这样写是不工作的!!!
查看pymongo的文档,会发现这么一段话——Starting with version 3.0 the
说白了,你这样try,是try不到任何东西的……见鬼!
官方也给了示例,你要这样子来判断你的连接是不是正常——
from pymongo.errors import ConnectionFailure
client = MongoClient()
try:
# The ismaster command is cheap and does not require auth.
client.admin.command('ismaster')
except ConnectionFailure:
print("Server not available")
而根据我的测试,client.admin.command('ismaster') 真的就得是在 client 后面调用才行,而在这个class的其它方法中,我调用的是具体的collection……
所以,我把代码改了一下下
class DbConnector:
def __init__(self):
with open(file="config.json", mode="r", encoding="utf-8") as self.dbinfo:
self.dbinfo = json.load(self.dbinfo)
self.client = MongoClient("mongodb://{}/".format(self.dbinfo["DB"]["hostlist"]))
self.db = self.client[self.dbinfo["DB"]["dbName"]]
def judge_connection(self):
try:
self.client.admin.command('ismaster')
except pymongo.errors.PyMongoError as e:
print("DB ERROR!")
client 前面加了个self. ,然后单独写了一个判断连接在不在的方法,每个具体的操作数据库的方法都会调用它一次
注意,这个方法最好是在你调用操作数据库的方法/函数内,不要全局调用,否则 import 的时候会发生意想不到的尴尬情况 :)
举个例子——
def query_many(self, clct: str, cond: dict, projection: str = None):
self.judge_connection()
clctObj = self.db[self.dbinfo["COLLECTION"][clct]]
results = clctObj.find(
filter=cond,
projection=projection
)
return results
差不多就这样,捕获客户端连接方面的异常不能直接在 MongoClient 的屁股后面调用,木有用,啥也 try 不到。