2015-05-29 2 views
20

В частности, я в настоящее время пытаюсь проверить, если подключение к клиенту действует с помощью следующей функции:Как вы можете проверить, действительно ли клиент для экземпляра MongoDB?

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) 
+0

pymongo.errors.ConnectionFailure выбрасывается, когда хост с client_uri недоступен, но если база данных не существует на хосте, она создана, поэтому вам нужно предварительно проверить существование db. – imarban

+0

Спасибо. Как вы проверяете существование db заранее? – Leeren

+0

Метод database_names в классе MongoClient может помочь. – imarban

ответ

30

Параметр serverSelectionTimeoutMS ключевого слова pymongo.mongo_client.MongoClient управления, как долго водитель будет пытаться подключиться к серверу. Значение по умолчанию - 30 секунд.

Установите его в очень низкое значение, совместимое с вашим типичным временем соединения¹, чтобы немедленно сообщить об ошибке. Вы должны запросить 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 
+1

Это хорошо работает. У меня возникла проблема: если для serverSelectionTimeoutMS установлено значение 0, всегда будет указано, что экземпляр MongoDB не работает. Установка этого параметра на 1 мс исправила эту проблему. –

+0

Спасибо, что указали, что @James! Я соответствующим образом обновил ответ. Вы используете * кластер * серверов MongoDB или * единственный сервер? –

+0

@SylvainLeroux Я просто использую один сервер :) –

0

Привет, чтобы узнать, что соединение установлено или вы не можете сделать это:

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

serverSelectionTimeoutMS

Это определяет, как долго блокировать выбор сервера, прежде чем выбрасывать исключение . Значение по умолчанию - 30 000 (миллисекунды). Он ДОЛЖЕН быть настраивается на уровне клиента. Он НЕ ДОЛЖЕН настраиваться на уровне объекта базы данных, объекта коллекции или на уровне отдельного запроса .

Это значение по умолчанию было выбрано для того, чтобы быть достаточным для первичного выбора основного сервера . Поскольку сервер улучшает скорость выборов , этот номер может быть изменен в сторону понижения.

Пользователи, которые могут переносить длительные задержки для выбора сервера, когда топология может установить это значение выше.Пользователи, которые хотят «сбой быстро», когда топология в потоке может установить это на небольшое число.

A serverSelectionTimeoutMS of zero МАЙ имеют специальное значение в некоторых драйверах; Значение нуля не определено в этой спецификации, но все драйверы ДОЛЖНЫ документировать значение нуля.

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 
0

serverSelectionTimeoutMS не работает для меня (Python 2.7.12, MongoDB 3.6.1, PyMongo 3.6.0). A. Jesse Jiryu Davis предложил в a GitHub issue, что мы сначала пытаемся подключить уровень сокета в качестве теста лакмусовой бумажки. Это делает трюк для меня.

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. 

Есть много проблем, это не будет ловить, но если сервер не работает или недоступен, это покажет вам сразу.

Смежные вопросы