Python 如何检查 MongoDB 实例的客户端是否有效?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30539183/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:36:58  来源:igfitidea点击:

How do you check if the client for a MongoDB instance is valid?

pythonmongodbpymongo

提问by Leeren

In particular, I am currently trying to check if a connection to a client is valid using the following function:

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

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

I then use this function like this:

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

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

Is there a way to catch and throw an exception at the last line if an invalid URI is given? I initially thought that's what the ConnectionFailure was for (so this could be caught when connecting) but I was wrong.

如果给出无效的 URI,有没有办法在最后一行捕获并抛出异常?我最初认为这就是 ConnectionFailure 的用途(因此在连接时可能会被捕获)但我错了。

If I run the program with an invalid URI, which fails to run, issuing a KeyboardInterrupt yields:

如果我使用无效的 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)

采纳答案by Sylvain Leroux

The serverSelectionTimeoutMSkeyword parameter of pymongo.mongo_client.MongoClientcontrols how long the driver will try to connect to a server. The default value is 30s.

serverSelectionTimeoutMS的关键字参数pymongo.mongo_client.MongoClient控制驱动多久尝试连接到服务器。默认值为 30 秒。

Set it to a very low value compatible with your typical connection time1 to immediately report an error. You need to query the DB after that to trigger a connection attempt :

将其设置为与您的典型连接时间兼容的非常低的值以立即报告错误。之后您需要查询数据库以触发连接尝试:

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

This will raise pymongo.errors.ServerSelectionTimeoutError.

这将提高pymongo.errors.ServerSelectionTimeoutError.

1 Apparentlysetting serverSelectionTimeoutMSto 0might even work in the particular case your server has very low latency (case of a "local" server with very light load for example)

1显然设置serverSelectionTimeoutMS0甚至可能在您的服务器延迟非常低的特定情况下工作(例如,负载非常轻的“本地”服务器的情况)



It is up to you to catch that exception and to handle it properly. Something likethat:

捕获该异常并正确处理它取决于您。什么的是:

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)

will display:

将显示:

No servers found yet

回答by Manochehr Rasouli

Hi to find out that the connection is established or not you can do that :

嗨,找出连接是否建立,您可以这样做:

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")

回答by The Demz

serverSelectionTimeoutMS

服务器选择超时MS

This defines how long to block for server selection before throwing an exception. The default is 30,000 (milliseconds). It MUST be configurable at the client level. It MUST NOT be configurable at the level of a database object, collection object, or at the level of an individual query.

This default value was chosen to be sufficient for a typical server primary election to complete. As the server improves the speed of elections, this number may be revised downward.

Users that can tolerate long delays for server selection when the topology is in flux can set this higher. Users that want to "fail fast" when the topology is in flux can set this to a small number.

A serverSelectionTimeoutMS of zero MAY have special meaning in some drivers; zero's meaning is not defined in this spec, but all drivers SHOULD document the meaning of zero.

这定义了在抛出异常之前阻止服务器选择的时间。默认值为 30,000(毫秒)。它必须可在客户端级别进行配置。它不得在数据库对象、集合对象或单个查询级别进行配置。

选择此默认值足以完成典型的服务器主选举。随着服务器提高选举速度,这个数字可能会向下修正。

当拓扑不断变化时,可以容忍服务器选择长时间延迟的用户可以将其设置得更高。想要在拓扑不断变化时“快速失败”的用户可以将其设置为一个较小的数字。

serverSelectionTimeoutMS 为零可能在某些驱动程序中具有特殊含义;本规范中没有定义零的含义,但所有驱动程序都应该记录零的含义。

https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#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

回答by ESV

serverSelectionTimeoutMSdoesn't work for me (Python 2.7.12, MongoDB 3.6.1, pymongo 3.6.0). A. Jesse Jiryu Davissuggested in a GitHub issuethat we attempt a socket-level connection first as a litmus test. This does the trick for me.

serverSelectionTimeoutMS对我不起作用(Python 2.7.12、MongoDB 3.6.1、pymongo 3.6.0)。 A. Jesse Jiryu DavisGitHub 问题中建议我们首先尝试套接字级连接作为试金石。这对我有用。

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.

There are plenty of problems this won't catch, but if the server isn't running or isn't reachable, this'll show you right away.

有很多问题不会被发现,但是如果服务器没有运行或无法访问,这会立即显示给您。