python 如何检查MongoDB示例的客户端是否有效?

3vpjnl9f  于 2023-06-04  发布在  Python
关注(0)|答案(7)|浏览(165)

特别是,我目前正在尝试使用以下函数检查到客户端的连接是否有效:

def mongodb_connect(client_uri):
    try:
        return pymongo.MongoClient(client_uri)
    except pymongo.errors.ConnectionFailure:
         print "Failed to connect to server {}".format(client_uri)

然后我这样使用这个函数:

def bucket_summary(self):
    client_uri = "some_client_uri"
    client = mongodb_connect(client_uri)
    db = client[tenant_id]
    ttb = db.timebucket.count() # If I use an invalid URI it hangs here

如果给出了无效的URI,是否有方法在最后一行捕获并抛出异常?我最初认为这就是ConnectionFailure的作用(因此在连接时可以捕获),但我错了。
如果我使用无效的URI运行程序,它无法运行,发出KeyboardInterrupt会产生:

File "reportjob_status.py", line 58, in <module>
tester.summarize_timebuckets()
File "reportjob_status.py", line 43, in summarize_timebuckets
ttb = db.timebucket.count() #error
File "/Library/Python/2.7/site-packages/pymongo/collection.py", line   1023, in count
return self._count(cmd)
File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 985, in _count
with self._socket_for_reads() as (sock_info, slave_ok):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 699, in _socket_for_reads
with self._get_socket(read_preference) as sock_info:
File  "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 663, in _get_socket
server = self._get_topology().select_server(selector)
File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 121, in select_server
address))
File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 106, in select_servers
self._condition.wait(common.MIN_HEARTBEAT_INTERVAL)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 358, in wait
_sleep(delay)
xuo3flqw

xuo3flqw1#

pymongo.mongo_client.MongoClientserverSelectionTimeoutMS关键字参数控制驱动程序将尝试连接到服务器的时间。默认值为30s。
将其设置为与您的典型连接时间兼容的非常低的值¹以立即报告错误。在此之后,您需要查询DB以触发连接尝试:

>>> maxSevSelDelay = 1 # Assume 1ms maximum server selection delay
>>> client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
                                 serverSelectionTimeoutMS=maxSevSelDelay)
//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>> client.server_info()

这将引发pymongo.errors.ServerSelectionTimeoutError
¹ * 显然 * 将serverSelectionTimeoutMS设置为0甚至可以在服务器延迟非常低的特定情况下工作(例如,负载非常轻的“本地”服务器)
捕获异常并正确处理它取决于您。类似的东西:

try:
    client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
                                     serverSelectionTimeoutMS=maxSevSelDelay)
    client.server_info() # force connection on a request as the
                         # connect=True parameter of MongoClient seems
                         # to be useless here 
except pymongo.errors.ServerSelectionTimeoutError as err:
    # do whatever you need
    print(err)

将显示:

No servers found yet
ldxq2e6h

ldxq2e6h2#

您好,要了解连接是否已建立,您可以执行以下操作:

from pymongo import MongoClient
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")
qq24tv8q

qq24tv8q3#

serverSelectionTimeoutMS

这定义了在引发异常之前阻止服务器选择的时间。默认值为30,000(毫秒)。它必须在客户端级别进行配置。它不能在数据库对象、集合对象或单个查询的级别上进行配置。
选择此默认值足以完成典型的服务器初选。随着服务器提高选举的速度,这个数字可能会向下修正。
当拓扑处于变化中时,可以容忍服务器选择的长延迟的用户可以将此设置得更高。如果用户希望在拓扑变化时“快速失败”,可以将此值设置为一个较小的数字。
零的serverSelectionTimeoutMS在某些驱动程序中可能有特殊含义;零的含义没有在这个规范中定义,但是所有的驱动都应该记录零的含义。
https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#serverselectiontimeoutms

# pymongo 3.5.1
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError

client = MongoClient("mongodb://localhost:27000/", serverSelectionTimeoutMS=10, connectTimeoutMS=20000)

try:
    info = client.server_info() # Forces a call.
except ServerSelectionTimeoutError:
    print("server is down.")

# If connection create a new one with serverSelectionTimeoutMS=30000
bpsygsoo

bpsygsoo4#

serverSelectionTimeoutMS不适合我(Python 2.7.12,MongoDB 3.6.1,pymongo 3.6.0)。A. Jesse Jiryu Davis在GitHub issue中建议我们首先尝试socket级别的连接作为试金石。这对我来说很有用。

def throw_if_mongodb_is_unavailable(host, port):
    import socket
    sock = None
    try:
        sock = socket.create_connection(
            (host, port),
            timeout=1) # one second
    except socket.error as err:
        raise EnvironmentError(
            "Can't connect to MongoDB at {host}:{port} because: {err}"
            .format(**locals()))
    finally:
        if sock is not None:
            sock.close()

# elsewhere...
HOST = 'localhost'
PORT = 27017
throw_if_mongodb_is_unavailable(HOST, PORT)
import pymongo
conn = pymongo.MongoClient(HOST, PORT)
print(conn.admin.command('ismaster'))
# etc.

有很多问题这不会赶上,但如果服务器没有运行或无法访问,这将显示你马上。

t40tm48m

t40tm48m5#

也可以这样检查:

from pymongo import MongoClient
from pymongo.errors import OperationFailure

def check_mongo_connection(client_uri):
    connection = MongoClient(client_uri)

    try:
        connection.database_names()
        print('Data Base Connection Established........')

    except OperationFailure as err:
        print(f"Data Base Connection failed. Error: {err}")

check_mongo_connection(client_uri)
gywdnpxw

gywdnpxw6#

对于pymongo >= 4.0,首选方法是使用ping命令instead of deprecated ismaster

from pymongo.errors import ConnectionFailure
client = MongoClient()

try:
    client.admin.command('ping')
except ConnectionFailure:
    print("Server not available")

要处理身份验证失败,请包括OperationFailure

except OperationFailure as err:
    print(f"Database error encountered: {err}")

来源:mongo_client.py

gijlo24d

gijlo24d7#

def mongo_available():
    maxsevseldelay = 1  # Assume 1ms maximum server selection delay
    client = pymongo.MongoClient('mongodb://localhost:27017,localhost2:27017',serverSelectionTimeoutMS=maxsevseldelay)
    try:
        # The ping command is cheap and does not require auth.
        client.admin.command('ping')
        return True, "Mongo connection working fine"
    except ConnectionFailure:
        return False, "Mongo Server not available"
        

mongo_available()
(False, 'Mongo Server not available')

相关问题