example create collection python mongodb pymongo

python - create - ¿Cómo verifica si el cliente para una instancia de MongoDB es válido?



python mongodb collection (4)

En particular, actualmente estoy tratando de verificar si una conexión a un cliente es válida usando la siguiente función:

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

Entonces uso esta función como esta:

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

¿Hay una manera de atrapar y lanzar una excepción en la última línea si se da un URI no válido? Inicialmente pensé que para eso era el ConnectionFailure (por lo que podría detectarse al conectarse) pero estaba equivocado.

Si ejecuto el programa con un URI no válido, que no puede ejecutarse, emitir un rendimiento 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)


El parámetro de la palabra clave serverSelectionTimeoutMS de pymongo.mongo_client.MongoClient controla cuánto tiempo intentará conectarse el controlador a un servidor. El valor predeterminado es 30s.

Establézcalo en un valor muy bajo compatible con su tiempo de conexión típico typical para informar inmediatamente de un error. Debe consultar el DB después de eso para desencadenar un intento de conexión:

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

Esto elevará pymongo.errors.ServerSelectionTimeoutError .

¹ Aparentemente, configurar serverSelectionTimeoutMS en 0 podría funcionar incluso en el caso particular de que su servidor tenga una latencia muy baja (caso de un servidor "local" con una carga muy ligera, por ejemplo)

Depende de usted capturar esa excepción y manejarla adecuadamente. Algo así :

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)

mostrará:

No servers found yet


Hola, para saber si la conexión está establecida o no, puedes hacer eso:

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


serverSelectionTimeoutMS no funciona para mí (Python 2.7.12, MongoDB 3.6.1, pymongo 3.6.0). A. Jesse Jiryu Davis sugirió en un problema de GitHub que primero intentemos una conexión a nivel de socket como una prueba de fuego. Esto hace el truco para mí.

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.

Hay muchos problemas que esto no detectará, pero si el servidor no se está ejecutando o no está disponible, se lo mostraremos de inmediato.


serverSelectionTimeoutMS

Esto define cuánto tiempo se debe bloquear la selección del servidor antes de lanzar una excepción. El valor predeterminado es 30,000 (milisegundos). DEBE ser configurable a nivel de cliente. NO DEBE ser configurable al nivel de un objeto de base de datos, objeto de colección, o al nivel de una consulta individual.

Se eligió este valor predeterminado para que sea suficiente para que se complete una elección primaria del servidor típico. A medida que el servidor mejora la velocidad de las elecciones, este número puede ser revisado a la baja.

Los usuarios que pueden tolerar largos retrasos para la selección del servidor cuando la topología está en flujo pueden establecer esto más alto. Los usuarios que desean "fallar rápido" cuando la topología está en flujo pueden establecer esto en un número pequeño.

Un serverSelectionTimeoutMS de cero PUEDE tener un significado especial en algunos controladores; El significado de cero no está definido en esta especificación, pero todos los controladores DEBEN documentar el significado de cero.

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