Docs Menu
Docs Home
/ /

Limite el tiempo de ejecución del servidor

Al usar PyMongo para realizar una operación en el servidor, también puede limitar el tiempo que el servidor tiene para finalizarla. Para ello, especifique un tiempo de espera para la operación en el cliente. Este tiempo aplica todos los pasos necesarios para completar la operación, incluyendo la selección del servidor, la verificación de la conexión, la serialización y la ejecución en el servidor. Cuando expira el tiempo de espera, PyMongo genera una excepción de tiempo de espera.

Puede especificar un tiempo de espera de dos maneras: utilizando el timeout() método o utilizando la opción de conexión timeoutMS.

Para especificar un tiempo de espera en su código, llame al método timeout() y pásele la duración del tiempo de espera, en segundos. Debe llamar al método timeout() en una instrucción with, como se muestra en el siguiente ejemplo:

with pymongo.timeout(10):
collection.insert_one({"name": "Yngwie"})

En el ejemplo anterior, si la operación de inserción no finaliza en 10 segundos, PyMongo genera un error.

El tiempo de espera especificado se aplica a todas las operaciones dentro del bloque with. En el siguiente ejemplo, las operaciones de inserción y búsqueda deben finalizar en un total de 10 segundos:

with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
coll.find_one({"name": "Yngwie"})

Cuando la ejecución entra en un bloque de timeout anidado, el timeout exterior se pausa. Cuando la ejecución sale del bloque anidado de tiempo de espera, se reanuda el tiempo de espera anterior.

Importante

Un bloque de tiempo de espera anidado puede acortar la fecha límite de un bloque de tiempo de espera externo, pero no puede extenderla.

El siguiente ejemplo muestra cómo utilizar llamadas anidadas al método timeout():

1with pymongo.timeout(5):
2 collection.find_one()
3 with pymongo.timeout(3):
4 collection.find_one()
5 collection.find_one()
6 with pymongo.timeout(10):
7 collection.find_one()
8 collection.find_one()

En el ejemplo anterior, el código realiza los siguientes pasos:

  • Línea:1 crea un bloque de tiempo de espera de cinco segundos.

  • 2Línea: Llama al find_one() método dentro del bloque de tiempo de espera de cinco segundos. El servidor debe
    Complete esta operación dentro del tiempo de espera de cinco segundos.
  • Línea:3 crea un bloque de tiempo de espera anidado de tres segundos.

  • 4Línea: Llama al find_one() método dentro del bloque de tiempo de espera de tres segundos. El servidor debe
    Complete esta operación en tres segundos.
  • 5Línea: Llama al find_one() método fuera del tiempo de espera de tres segundos. El servidor debe
    Complete esta operación dentro del tiempo de espera original de cinco segundos.
  • Línea:6 crea un bloque de tiempo de espera anidado de diez segundos.

  • 7Línea: Llama al find_one() método dentro del bloque de tiempo de espera de diez segundos. Un tiempo de espera anidado
    El bloque no puede extender un bloque externo de tiempo de espera, por lo que el servidor debe completar esta operación dentro del tiempo de espera original de cinco segundos.
  • 8Línea: Llama al find_one() método fuera del tiempo de espera de diez segundos. El servidor debe completar esta operación dentro del tiempo de espera original de cinco segundos.

El método timeout() es seguro para subprocesos. El tiempo de espera solo se aplica al subproceso actual, y varios subprocesos pueden configurar diferentes tiempos de espera en paralelo.

El método timeout() también es seguro contra asyncio. El tiempo de espera solo se aplica a la tarea actual, y varias tareas pueden configurar diferentes tiempos de espera simultáneamente.

El siguiente ejemplo muestra cómo utilizar el método timeout() con Motor, el controlador Python de MongoDB para aplicaciones asincrónicas:

import motor.motor_asyncio
client = motor.motor_asyncio.AsyncIOMotorClient()
coll = client["test-db"]["test-collection"]
with pymongo.timeout(10):
await coll.insert_one({"name": "Yngwie"})
await coll.find_one({"name": "Yngwie"})

Para especificar un tiempo de espera al conectarse a una implementación de MongoDB, configure la opción de conexión timeoutMS con la duración del tiempo de espera, en milisegundos. Puede hacerlo de dos maneras: pasando un argumento al constructor MongoClient o mediante un parámetro en su cadena de conexión.

Los siguientes ejemplos de código utilizan la opción timeoutMS para especificar un tiempo de espera de 10 segundos:

client = pymongo.MongoClient("mongodb://<db_username>:<db_password>@<hostname:<port>",
timeoutMS=10000)
uri = "mongodb://<db_username>:<db_password>@<hostname:<port>/?timeoutMS=10000"
client = pymongo.MongoClient(uri)

Si especifica la opción timeoutMS, PyMongo aplica automáticamente el tiempo de espera especificado a cada operación del servidor. Los siguientes ejemplos de código especifican un tiempo de espera de 10 segundos y luego invocan los métodos insert_one() y find_one(). Para comparar la opción timeoutMS con el método timeout(), seleccione la pestaña correspondiente.

uri = "mongodb://<db_username>:<db_password>@<hostname@:<port>/?timeoutMS=10000"
client = pymongo.MongoClient(uri)
coll = client["test-db"]["test-collection"]
coll.insert_one({"name": "Yngwie"}) # Uses a 10-second timeout.
coll.find_one({"name": "Yngwie"}) # Also uses a 10-second timeout.
client = MongoClient()
coll = client["test-db"]["test-collection"]
with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
with pymongo.timeout(10):
coll.find_one({"name": "Yngwie"})

Importante

timeout() Anula timeoutMS

Si especifica la opción timeoutMS y luego llama al método timeout() en su código, PyMongo ignora el valor timeoutMS dentro del bloque timeout:

client = MongoClient("mongodb://localhost/?timeoutMS=10000")
coll = client["test-db"]["test-collection"]
coll.insert_one({"name": "Yngwie"}) # Uses the client's 10-second timeout
# pymongo.timeout overrides the client's timeoutMS.
with pymongo.timeout(20):
coll.insert_one({"name": "Yngwie"}) # Uses the 20-second timeout
with pymongo.timeout(5):
coll.find_one({"name": "Yngwie"}) # Uses the 5-second timeout

Cuando una operación del servidor excede el tiempo de espera especificado, PyMongo genera una excepción de tiempo de espera y establece la propiedad PyMongoError.timeout en True.

El siguiente ejemplo de código muestra una forma de gestionar una excepción de tiempo de espera. Dentro del bloque except, el código comprueba la propiedad timeout para determinar si la excepción se debió a un tiempo de espera.

try:
with pymongo.timeout(10):
coll.insert_one({"name": "Yngwie"})
time.sleep(10)
# The deadline has now expired. The next operation will raise
# a timeout exception.
coll.find_one({"name": "Yngwie"})
except PyMongoError as exc:
if exc.timeout:
print(f"block timed out: {exc!r}")
else:
print(f"failed with non-timeout error: {exc!r}")

Las siguientes secciones describen errores que puede ver al usar tiempos de espera.

Este error indica que el cliente no pudo encontrar un servidor disponible para ejecutar la operación dentro del tiempo de espera indicado:

pymongo.errors.ServerSelectionTimeoutError: No servers found yet, Timeout: -0.00202266700216569s, Topology Description: <TopologyDescription id: 63698e87cebfd22ab1bd2ae0, topology_type: Unknown, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None>]>

Este error indica que el cliente no pudo establecer una conexión dentro del tiempo de espera dado o que la operación se envió pero el servidor no respondió a tiempo:

pymongo.errors.NetworkTimeout: localhost:27017: timed out

Este error podría indicar que el servidor canceló la operación porque se excedió el tiempo de espera establecido. Incluso si PyMongo genera esta excepción, es posible que la operación se haya completado parcialmente en el servidor.

pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'}

También podría indicar que el cliente canceló la operación porque no fue posible completarla dentro del tiempo de espera indicado:

pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427

Este error indica que el servidor no pudo completar la operación de escritura solicitada dentro del tiempo de espera indicado y siguiendo el problema de escritura especificado:

pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}

Este error indica que el servidor no pudo completar un método insert_many() o bulk_write() dentro del tiempo de espera indicado y siguiendo el problema de escritura especificado:

pymongo.errors.BulkWriteError: batch op errors occurred, full error: {'writeErrors': [], 'writeConcernErrors': [{'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []}

Para obtener más información sobre el uso de timeouts en PyMongo, consulta la siguiente documentación de la API:

Volver

Stable API

En esta página