Menu Docs
Página inicial do Docs
/ / /
PyMongo
/

Limitar o tempo de execução do servidor MongoDB

Nesta página

  • Visão geral
  • Método de timeout()
  • Blocos de tempo limite aninhados
  • Segurança de thread e tarefa
  • Opção de conexão timeoutMS
  • Tratamento de exceções
  • Solução de problemas
  • ServerSelectionTimeoutError
  • NetworkTimeout
  • ExecutionTimeout
  • WTimeoutError
  • BulkWriteError
  • Documentação da API

Ao usar o PyMongo para executar uma operação de servidor, você também pode limitar o tempo que o servidor tem para concluir a operação. Para isso, especifique um tempo limite de operação do lado do cliente. O tempo limite aplica todas as etapas necessárias para concluir a operação, incluindo seleção do servidor, verificação da conexão, serialização e execução do lado do servidor. Quando o tempo limite expira, o PyMongo gera uma exceção de tempo limite.

Você pode especificar um tempo limite de duas maneiras: usando o método timeout() ou usando a opção de conexão timeoutMS .

Para especificar um tempo limite em seu código, chame o método timeout() e passe a duração do tempo limite, em segundos. Você deve chamar o método timeout() em uma declaração with , como mostrado no seguinte exemplo:

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

No exemplo anterior, se a operação de inserção não terminar dentro de 10 segundos, o PyMongo reportará um erro.

O timeout que você especifica se aplica a todas as operações dentro do bloco with . No exemplo a seguir, as operações de inserção e localização devem terminar dentro de um total de 10 segundos:

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

Quando a execução insere um bloco de tempo limite aninhado, o tempo limite externo é pausado. Quando a execução sai do bloco de tempo limite aninhado, o tempo limite anterior é retomado.

Importante

Um bloqueio de tempo limite aninhado pode reduzir o prazo de um bloqueio de tempo limite externo, mas não pode estenda-o.

O exemplo seguinte mostra como utilizar chamadas aninhadas para o 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()

No exemplo anterior, o código executa as seguintes etapas:

  • Linha 1: cria um bloco de tempo limite de cinco segundos.

  • Linha 2: chama o método find_one() dentro do bloco de tempo limite de cinco segundos. O servidor deve
    conclua esta operação dentro do tempo limite de cinco segundos.
  • Linha 3: cria um bloco de tempo limite de três segundos aninhado.

  • Linha 4: chama o método find_one() dentro do bloco de tempo limite de três segundos. O servidor deve
    conclua esta operação dentro de três segundos.
  • Linha 5: chama o método find_one() fora do bloco de tempo limite de três segundos. O servidor deve
    conclua esta operação dentro do tempo limite original de cinco segundos.
  • Linha 6: cria um bloco de tempo limite de dez segundos aninhado.

  • Linha 7: chama o método find_one() dentro do bloco de tempo limite de dez segundos. Um tempo limite aninhado
    o bloco não pode estender um bloco de tempo limite externo, portanto, o servidor deve concluir essa operação dentro do tempo limite original de cinco segundos.
  • Linha 8: chama o método find_one() fora do bloco de tempo limite de dez segundos. O servidor deve concluir esta operação dentro do tempo limite original de cinco segundos.

O método timeout() é seguro para thread. O tempo limite se aplica somente ao thread atual, e vários threads podem configurar diferentes tempos limite em paralelo.

O método timeout() também é asyncioseguro. O tempo limite se aplica apenas à Tarefa atual, e várias Tarefas podem configurar tempos limite diferentes ao mesmo tempo.

O exemplo a seguir mostra como usar o timeout() método com Motor, o driver Python do MongoDB para aplicativos assíncronos:

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 um tempo limite ao se conectar a um sistema do MongoDB, defina a opção de conexão timeoutMS para o comprimento de tempo limite, em milissegundos. Você pode fazer isso de duas maneiras: passando um argumento para o construtor MongoClient ou por meio de um parâmetro em sua connection string.

Os seguintes exemplos de código utilizam a opção timeoutMS para especificar um tempo limite 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)

Se você especificar a opção timeoutMS , o PyMongo aplicará automaticamente o tempo limite especificado para cada operação do servidor. Os exemplos de código a seguir especificam um tempo limite de 10 segundos e, em seguida, chamam os métodos insert_one() e find_one() . Para ver como a opção timeoutMS se compara ao uso do método timeout() , selecione a guia correspondente.

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() Substitui timeoutMS

Se você especificar a opção timeoutMS e, em seguida, chamar o método timeout() em seu código, o PyMongo ignorará o valor timeoutMS dentro do bloco 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

Quando uma operação de servidor excede o tempo limite especificado, o PyMongo gera uma exceção de tempo limite e define a propriedade PyMongoError.timeout como True.

O exemplo de código a seguir mostra uma maneira de lidar com uma exceção de tempo limite. Dentro do bloco except , o código verifica a propriedade timeout para determinar se a exceção foi causada por um tempo limite.

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

As seções a seguir descrevem erros que você pode ver ao usar tempos limite.

Este erro indica que o cliente não conseguiu encontrar um servidor disponível para executar a operação dentro do tempo limite fornecido:

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>]>

Esse erro indica que o cliente não conseguiu estabelecer uma conexão dentro do tempo limite fornecido ou que a operação foi enviada, mas o servidor não responde a tempo:

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

Esse erro pode indicar que o servidor cancelou a operação porque excedeu o tempo limite fornecido. Mesmo que o PyMongo gere essa exceção, a operação pode ter sido concluída parcialmente no servidor.

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

Isso também pode indicar que o cliente cancelou a operação porque não foi possível concluí-la dentro do tempo limite fornecido:

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

Este erro indica que o servidor não conseguiu concluir a operação de gravação solicitada dentro do tempo limite fornecido e após a write concern especificada:

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

Esse erro indica que o servidor não conseguiu concluir um método insert_many() ou bulk_write() dentro do tempo limite fornecido e após a write concern especificada:

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 saber mais sobre como usar tempos limite no PyMongo, consulte a seguinte documentação da API:

Voltar

Stable API