Limit Server Execution Time
On this page
Overview
When you use PyMongo to perform a server operation, you can also limit the amount of time the server has to finish this operation. To do so, specify a client-side operation timeout. The timeout applies all steps needed to complete the operation, including server selection, connection checkout, serialization, and server-side execution. When the timeout expires, PyMongo raises a timeout exception.
You can specify a timeout in two ways: by using the timeout()
method or by using
the timeoutMS
connection option.
timeout() Method
To specify a timeout in your code, call the timeout()
method and pass it the timeout
length, in seconds. You must call the timeout()
method
in a with
statement, as shown in the following example:
with pymongo.timeout(10): collection.insert_one({"name": "Yngwie"})
In the preceding example, if the insert operation doesn't finish within 10 seconds, PyMongo raises an error.
The timeout you specify applies to all operations inside the with
block. In the
following example, the insert and find operations must both finish within a total of
10 seconds:
with pymongo.timeout(10): coll.insert_one({"name": "Yngwie"}) coll.find_one({"name": "Yngwie"})
Nested Timeout Blocks
When execution enters a nested timeout block, the outer timeout is paused. When execution exits the nested timeout block, the previous timeout resumes.
Important
A nested timeout block can shorten the deadline of an outer timeout block, but it can't extend it.
The following example shows how to use nested calls to the timeout()
method:
1 with 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()
In the preceding example, the code performs the following steps:
Line 1: Creates a five-second timeout block.
- Line 2: Calls the
find_one()
method inside the five-second timeout block. The server must - complete this operation within the five-second timeout.
- Line 2: Calls the
Line 3: Creates a nested three-second timeout block.
- Line 4: Calls the
find_one()
method inside the three-second timeout block. The server must - complete this operation within three seconds.
- Line 4: Calls the
- Line 5: Calls the
find_one()
method outside the three-second timeout block. The server must - complete this operation within the original five-second timeout.
- Line 5: Calls the
Line 6: Creates a nested ten-second timeout block.
- Line 7: Calls the
find_one()
method inside the ten-second timeout block. A nested timeout - block can't extend an outer timeout block, so the server must complete this operation within the original five-second timeout.
- Line 7: Calls the
Line 8: Calls the
find_one()
method outside the ten-second timeout block. The server must complete this operation within the original five-second timeout.
Thread and Task Safety
The timeout()
method is thread-safe. The timeout applies only to the current
thread, and multiple threads can configure different timeouts in parallel.
The timeout()
method is also asyncio
-safe. The timeout applies only to the
current Task, and multiple Tasks can configure different timeouts at the same time.
The following example shows how to use the timeout()
method with
Motor, the MongoDB
Python driver for asynchronous applications:
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"})
timeoutMS Connection Option
To specify a timeout when connecting to a MongoDB deployment, set the timeoutMS
connection option to the timeout length, in milliseconds.
You can do this in two ways: by passing an argument to the
MongoClient
constructor or through a parameter in your connection string.
The following code examples use the timeoutMS
option to specify a timeout of 10 seconds:
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)
If you specify the timeoutMS
option, PyMongo automatically applies the
specified timeout to each server operation. The following code examples specify
a timeout of 10 seconds, then call the insert_one()
and
find_one()
methods. To see how the timeoutMS
option compares to using the
timeout()
method, select the corresponding tab.
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"})
Important
timeout() Overrides timeoutMS
If you specify the timeoutMS
option, then call the timeout()
method
in your code, PyMongo ignores the timeoutMS
value inside the timeout
block:
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
Handling Exceptions
When a server operation exceeds the specified timeout, PyMongo
raises a timeout exception and sets the PyMongoError.timeout
property to True
.
The following code example shows one way to handle a timeout exception. Inside the
except
block, the code checks the timeout
property to determine whether
the exception was caused by a timeout.
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}")
Troubleshooting
The following sections describe errors you might see when using timeouts.
ServerSelectionTimeoutError
This error indicates that the client couldn't find an available server to run the operation within the given timeout:
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>]>
NetworkTimeout
This error indicates either that the client couldn't establish a connection within the given timeout or that the operation was sent but the server didn't respond in time:
pymongo.errors.NetworkTimeout: localhost:27017: timed out
ExecutionTimeout
This error might indicate that the server cancelled the operation because it exceeded the given timeout. Even if PyMongo raises this exception, the operation might have partially completed on the server.
pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'}
It also might indicate that the client cancelled the operation because it wasn't possible to complete it within the given timeout:
pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427
WTimeoutError
This error indicates that the server couldn't complete the requested write operation within the given timeout and following the specified write concern:
pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}
BulkWriteError
This error indicates that the server couldn't complete an insert_many()
or bulk_write()
method within the given timeout and following the specified
write concern:
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': []}
API Documentation
To learn more about using timeouts in PyMongo, see the following API documentation: