Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Managing Settings

00:00 Managing Settings One of the most popular ways to configure Python applications is with environment variables. An environment variable is a variable that lives in the operating system outside of your Python code, but can be read by your code or other programs.

00:15 Examples of this kind of data include secret keys, database credentials, API credentials, server addresses, and access tokens. Environment variables often change between development and production and many contain sensitive information.

00:31 Because of this, you need a robust way to pass, validate, and integrate environment variables into your code. This is a perfect use of pydantic-settings and that’s what you’ll be exploring in this section.

00:45 pydantic-settings is one of the most powerful ways to manage environment variables in Python, and it’s been widely adopted and recommended by popular libraries such as FastAPI.

00:55 You can use pydantic-settings to create models similar to BaseModel that pass and validate environment variables. The main class in pydantic-settings is BaseSettings, and it has all the same functionalities as BaseModel.

01:10 But if you create a model that inherits from BaseSettings, the model initializer will try to read any fields not passed as keyword arguments from environment variables.

01:20 Let’s suppose your application connects to a database and another API service. Your database credentials and API key can change over time and often change depending on which environment you are deploying in.

01:32 To handle this, you can create a BaseSettings model. You import the dependencies needed to create the BaseSettings model. Notice that you import BaseSettings from pydantic_settings with an underscore instead of a dash.

01:48 You then define a model AppConfig that inherits from BaseSettings.

01:56 It stores fields about the database and the API key. In this example, database_host has to be a valid HTTP URL, and the remaining fields have minimum length constraints.

02:16 Next, you’ll need to create environment variables. If you’re on Linux, macOS, or Windows Bash, you can do this with the export command.

02:43 If you need to know how to do this for Windows PowerShell, Real Python has you covered with this article.

02:51 Next, open a Python REPL and instantiate AppConfig.

03:02 Notice how no field names are specified when instantiating AppConfig. The BaseSettings model reads the fields from the environment variables.

03:11 Notice that you exported the environment variables in all capital letters, but AppConfig passed and stored them successfully. This is because BaseSettings is not case sensitive when matching environment variables to field names.

03:24 Next, close the REPL and create invalid environment variables.

03:40 Open a new REPL and re-instantiate AppConfig.

03:46 This time, pydantic_settings throws errors saying the database_host is not a valid URL and the remaining fields don’t meet the minimum length constraint.

03:55 While this is a simplified configuration example, you can leverage BaseSettings to pass and validate just about anything you need to from your environment variables. Any validation you can do with BaseModel can be done with BaseSettings including custom validation with model and field validators.

04:13 Finally, you’ll learn how to further customize the behavior of BaseSettings with SettingsConfigDict. Suppose you can’t manually export each of your environment variables, which is often the case, and you need to read them from a .env file.

04:28 You’d want to make sure that BaseSettings is case sensitive when passing, and there are no additional environment variables in the .env file aside from the ones you specify in your model. On screen, you’ll see how to do this with SettingsConfigDict.

04:45 You import SettingsConfigDict and initialize it within AppConfig.

04:53 Within SettingsConfigDict, you specify that the environment variable should be read from a .env file, case sensitivity should be enforced, and the extra environment variables are forbidden within the file.

05:11 Next, create a file named .env in the same directory as settings_management.py and populate it with the environment variables seen on screen.

05:33 Once again, open a Python REPL and instantiate your AppConfig model.

05:40 As you can see, AppConfig successfully passed and validated the environment variables in the .env file. Finally, to check the validation, add some invalid variables to the .env file. Change database_host to DATABASE_HOST in uppercase, violating the case sensitivity constraint, and also add an extra environment variable at the end that shouldn’t be there.

06:07 For the final time, open a new REPL and instantiate AppConfig. You get a list of errors saying that database_host is missing and you have an extra environment variable in the .env file.

06:19 Notice that because of the case sensitivity constraint, the model thinks that the uppercase DATABASE_HOST is an extra variable along with the extra value added at the end.

06:30 There’s a lot more you can do with SettingsConfigDict, and BaseSettings more generally, but these examples should give you an idea of how you can use pydantic-settings to manage your environment variables for your own use case.

06:43 In the next section of the course, you’ll take a look back at what you’ve learned.

Become a Member to join the conversation.