客户端操作超时#

推出了PyMongo 4.2 timeout() 以及 timeoutMS URI和关键字参数 MongoClient 。这些功能允许应用程序更轻松地限制一个或多个操作在控制权交还给应用程序之前可以执行的时间量。此超时适用于执行操作所做的所有工作,包括但不限于服务器选择、连接签出、序列化和服务器端执行。

基本用法#

下面的示例使用 timeout() 要配置10秒的超时 insert_one() 操作::

import pymongo
with pymongo.timeout(10):
    coll.insert_one({"name": "Nunu"})

这个 timeout() 适用于块内的所有pymongo操作。下面的示例确保 insert 以及 find 在总共10秒内完成,或引发超时错误::

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

当嵌套时 timeout() ,嵌套的截止日期由外部截止日期设置上限。最后期限只能缩短,不能延长。退出块时,将恢复之前的截止日期::

with pymongo.timeout(5):
    coll.find_one()  # Uses the 5 second deadline.
    with pymongo.timeout(3):
        coll.find_one() # Uses the 3 second deadline.
    coll.find_one()  # Uses the original 5 second deadline.
    with pymongo.timeout(10):
        coll.find_one()  # Still uses the original 5 second deadline.
    coll.find_one()  # Uses the original 5 second deadline.

超时错误#

timeout() 如果输入WITH-STATEMENT,则会为整个块设置一个截止日期。当超过该期限时,任何阻塞的pymongo操作都将引发超时异常。例如::

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

这个 pymongo.errors.PyMongoError.timeout 属性(在PyMongo 4.2中添加)将是 True 当错误是由超时和 False 否则的话。

TimeoutMS URI选项#

PyMongo 4.2还添加了对 timeoutMS URI和关键字参数 MongoClient 。配置此选项后,客户端将自动对每个API调用应用超时。例如::

client = MongoClient("mongodb://localhost/?timeoutMS=10000")
coll = client.test.test
coll.insert_one({"name": "Nunu"})  # Uses a 10-second timeout.
coll.find_one({"name": "Nunu"})  # Also uses a 10-second timeout.

以上大致相当于:

client = MongoClient()
coll = client.test.test
with pymongo.timeout(10):
    coll.insert_one({"name": "Nunu"})
with pymongo.timeout(10):
    coll.find_one({"name": "Nunu"})

Pymongo.timeout覆盖超时MS#

timeout() 覆盖 timeoutMS ;在 timeout() 阻止客户端的 timeoutMS 选项被忽略::

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

Pymongo.timeout是线程安全的#

timeout() 是线程安全的;超时仅适用于当前线程,多个线程可以并行配置不同的超时。

PYMOGO。超时是安全的#

timeout() Asyncio安全;超时仅适用于当前任务,多个任务可以同时配置不同的超时。 timeout() 可以相同地用于 Motor ,例如::

import motor.motor_asyncio
client = motor.motor_asyncio.AsyncIOMotorClient()
coll = client.test.test
with pymongo.timeout(10):
    await coll.insert_one({"name": "Nunu"})
    await coll.find_one({"name": "Nunu"})

故障排除#

根据超时时间的不同,可能会引发许多超时错误。在代码中,可以用 pymongo.errors.PyMongoError.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>]>

当客户端无法在给定超时内建立连接,或者操作已发送但服务器无法及时响应时:

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

当服务器因超过给定的超时而取消操作时。请注意,该操作可能已在服务器上部分完成(取决于操作):

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

当客户端因无法在给定超时内完成操作而取消操作时:

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

当客户端尝试写入操作,但服务器无法在给定超时内复制该写入(根据配置的写入问题)时:

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

与上面相同的错误,但 insert_many()bulk_write() **

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': []}