Skip to content

PYTHON-3606 - Document best practice for closing MongoClients and cursors #2465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pymongo/asynchronous/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,15 @@ def find(self, *args: Any, **kwargs: Any) -> AsyncCursor[_DocumentType]:
improper type. Returns an instance of
:class:`~pymongo.asynchronous.cursor.AsyncCursor` corresponding to this query.

Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include this note in any other places? Like Cursor or CommandCursor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We explicitly say users shouldn't create those classes directly. Is adding this still useful for our own internal documentation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering because this is only in find() but there are other methods that create cursors, the most important being aggregate().

If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
or use the cursor in a with statement::

async with collection.find() as cursor:
async for doc in cursor:
print(doc)

The :meth:`find` method obeys the :attr:`read_preference` of
this :class:`AsyncCollection`.

Expand Down
6 changes: 6 additions & 0 deletions pymongo/asynchronous/mongo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ def __init__(
exception (recognizing that the operation failed) and then continue to
execute.

Best practice is to call :meth:`AsyncMongoClient.close` when the client is no longer needed,
or use the client in a with statement::

async with AsyncMongoClient(url) as client:
# Use client here.

The `host` parameter can be a full `mongodb URI
<https://dochub.mongodb.org/core/connections>`_, in addition to
a simple hostname. It can also be a list of hostnames but no more
Expand Down
9 changes: 9 additions & 0 deletions pymongo/synchronous/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,15 @@ def find(self, *args: Any, **kwargs: Any) -> Cursor[_DocumentType]:
improper type. Returns an instance of
:class:`~pymongo.cursor.Cursor` corresponding to this query.

Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
or use the cursor in a with statement::

with collection.find() as cursor:
for doc in cursor:
print(doc)

The :meth:`find` method obeys the :attr:`read_preference` of
this :class:`Collection`.

Expand Down
6 changes: 6 additions & 0 deletions pymongo/synchronous/mongo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ def __init__(
exception (recognizing that the operation failed) and then continue to
execute.

Best practice is to call :meth:`MongoClient.close` when the client is no longer needed,
or use the client in a with statement::

with MongoClient(url) as client:
# Use client here.

The `host` parameter can be a full `mongodb URI
<https://dochub.mongodb.org/core/connections>`_, in addition to
a simple hostname. It can also be a list of hostnames but no more
Expand Down
Loading