Connecting to MongoDB Atlas using Motor

I’m trying to work with the Motor driver with Asyncio in connecting to Atlas. When I follow the official guide and use my Atlas connection string I get the following error:

pymongo.errors.ConfigurationError: The "dnspython" module must be installed to use mongodb+srv:// URIs. To fix this error install pymongo with the srv extra: /path/to/virtualenvs/PK76f_xS/bin/python -m pip install "pymongo[srv]"

I don’t have PyMongo installed because I’m using Motor so I’m confused as to why I need to install it to use Motor. Am I doing something wrong or is this error and subsequent installation required to work with Motor and Asyncio?

Thanks.

Welcome to the MongoDB Community @Ian!

PyMongo is a dependency of Motor, and will automatically be installed with motor.

PyMongo has several optional dependencies for features like different authentication, connection, and compression methods. dnspython is currently not installed by default.

Per the error message, the dnspython module must be installed in order to use mongodb+srv:// URIs. You can use the provided syntax or install using: python -m pip install dnspython.

Regards,
Stennie

1 Like

Thanks @Stennie_X,

I didn’t realise PyMongo was a dependency of Motor.

Are there any good examples of working with Motor? The guide shows a single function to connection and then leaves you on your own. Other tutorials I’ve seen like this one, suggest dropping the connection details in your code and presumably re-using the connection on every request?

The official docs seem to suggest running the event loop on every function call?

I’m a little confused as to how to set things up. Are you able to clarify or provide a good example codebase I can look through?

Thanks again.

Hi @ian,

Since older versions of Python don’t support top-level await calls, so the Motor tutorial in the documentation uses:

>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(do_find())

In general you just need to run your asyncio app like normal via asyncio.run() and start using the AsyncIOMotorClient.

Here is a concise example app (thanks to @Shane on the Python driver team):

import asyncio
import motor.motor_asyncio

async def main():
    client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017')
    coll = client.test.test
    await coll.insert_one({'hello': 'world'})
    print(await coll.find_one())

if __name__ == "__main__":
    asyncio.run(main())

If you are looking for more comprehensive Python examples, check out the MongoDB Developer Hub (Python).

Here are some articles (with associated GitHub repos) that may be of interest if you want to use Motor with different web frameworks:

Regards,
Stennie

1 Like

Super helpful, thanks @Stennie_X

So, just for clarity, if I’m using newer version of Python (3.6+ ?) then I don’t need to set the loop as in the documented example but can just run with asyncio.run()?

And from your concise example it looks like the database connection code can be extracted to a database.py file and imported, the same as with PyMongo connection code? This same connection would be shared among all requests to the database?

I just wanted to confirm that because I came across another article which said the opposite:

Unlike PyMongo you can’t declare the mongoDB initialisation in the top. Here you have to initialise on every function that want to access the mongoDB.