Skip to main content
April 2, 2026Brian McClain/6 min read

API Keys - Using Environment Variables in Python Projects

Secure your Python applications with environment variables

Security Risk Alert

Hard coding API keys directly in your Python scripts creates a significant security vulnerability. If your code is pushed to GitHub or shared publicly, your API key becomes exposed to anyone who views the repository.

Common Security Vulnerabilities

Exposed API Keys

API keys hard-coded in source files can be discovered by malicious actors. This leads to unauthorized usage and potential billing issues.

Version Control Exposure

Pushing sensitive data to GitHub or other repositories makes it permanently accessible in commit history. Even deleting it later doesn't remove the historical record.

Password Storage

Database passwords and other credentials stored in plain text within code files create multiple attack vectors for data breaches.

Setting Up Environment Variables

1

Create .env File

Create a new file named .env at the root level of your project, alongside your server files. This file has no name, only the .env extension.

2

Add Variables

Paste your API key variable into the .env file without quotes or spaces around the value. Use the format VARIABLE_NAME=value.

3

Install dotenv

Install the Python-dotenv package using pip install Python-dotenv to enable loading environment variables in your Python application.

4

Load Variables

Import load_dotenv and call it in your Python script, then use os.getenv to access your environment variables securely.

Before vs After: API Key Storage

FeatureInsecure MethodSecure Method
Storage LocationDirectly in Python fileSeparate .env file
Version Control RiskHigh - exposed in commitsLow - .env excluded
Code ReadabilityAPI key visible to allClean, no sensitive data
Security LevelVulnerableProtected
Recommended: Always use environment variables for sensitive data like API keys, passwords, and database credentials.
Check Existing Installations

Before installing new packages, use 'pip show package-name' to check if a module is already installed. This helps avoid unnecessary installations and potential conflicts.

Environment variables exist as key-value pairs, which is why OPENAI_API_KEY is in quotes when using os.getenv - we're referencing a key, not a regular variable name.
Understanding the difference between Python variables and environment variables is crucial for proper implementation.

Environment Variable Implementation Checklist

0/8

Environment Variables vs Hard-Coded Values

Pros
Keeps sensitive data out of source code
Prevents accidental exposure in version control
Allows different values for different environments
Follows security best practices
Makes code more portable and configurable
Cons
Requires additional setup and dependencies
Adds complexity to deployment process
Need to manage .env files separately
Potential for missing environment variables in production

This lesson is a preview from our Python for AI Course Online (includes software) and Python Certification Course Online (includes software & exam). Enroll in a course for detailed lessons, live instructor support, and project-based training.

Welcome back to this comprehensive AI development course using Python, where we're building production-ready applications with the OpenAI API, Flask, and JavaScript. I'm Brian McLean, and I'm excited to guide you through these advanced concepts.

Congratulations on reaching lesson 15—your persistence is paying off. Today we're addressing a critical security vulnerability that's been lurking in our codebase. Throughout this course, we've been storing our OpenAI API key directly in our server file as plain text. This represents a significant security risk that we need to resolve immediately.

Consider this scenario: you've built an impressive AI application and want to showcase it on GitHub, or you're collaborating with team members through version control. The moment you push that code to a public repository, your API key becomes visible to anyone who stumbles across your project. Malicious actors actively scan GitHub for exposed API keys, and yours could be harvested within minutes of being published. Beyond API keys, this same vulnerability affects database passwords, authentication tokens, and other sensitive credentials that power modern applications.

For this lesson, we'll continue working in our existing server03.py file since we're making focused security improvements rather than adding new features. This approach demonstrates how security enhancements can be retrofitted into existing codebases—a common real-world scenario you'll encounter in professional development.

Let's examine our current vulnerability. Here's our OpenAI API key, sitting exposed in plain sight within our source code. This represents exactly the kind of security oversight that can compromise entire applications and violate best practices established across the software industry.

The solution is implementing environment variables through a `.env` file—a widely adopted industry standard for managing sensitive configuration data. This file exists outside your main codebase and contains key-value pairs for sensitive information. We'll utilize Python's `dotenv` module to seamlessly load these variables into our application at runtime, maintaining functionality while dramatically improving security posture.

Now let's dive into the implementation. According to our lesson materials, we're covering "Securing API Key as Environment Variable"—a fundamental skill that every professional developer must master. Hard-coding sensitive data directly into source code violates basic security principles and creates unnecessary risk for both personal projects and enterprise applications.

**Step 1: Creating the Environment File**

Navigate to your project's root directory—the same level where your server files reside. Create a new file named exactly `.env` (note: this file has no name, only an extension). This naming convention is universally recognized across development platforms and deployment environments.

Within your `.env` file, add your OpenAI API key using this format: `OPENAI_API_KEY=your_actual_key_here`. Notice there are no quotes, spaces around the equals sign, or trailing spaces—the `dotenv` module expects this specific format for proper parsing.

Before removing the API key from your server file, comment it out rather than deleting it entirely. This provides a safety net during the transition—if our environment variable implementation encounters issues, we can quickly revert to the working version without having to locate and re-enter the API key.


**Step 2: Installing and Configuring the dotenv Module**

First, let's verify whether `dotenv` is already installed in your current virtual environment. In your terminal, execute: `pip show python-dotenv`. If you see "WARNING: Package(s) not found", that's exactly what we want—it confirms we're starting with a clean installation.

Install the module using: `pip install python-dotenv`. This package is actively maintained and widely used across Python projects for environment variable management. The installation process may prompt you to upgrade pip itself—I recommend accepting these updates to ensure you're working with the latest security patches and features.

Note that we're installing this in our project's virtual environment. If you've worked with `dotenv` in previous projects, you'll need to install it again for each isolated environment—this is the intended behavior and ensures dependency management remains clean and predictable.

**Step 3: Implementing Environment Variable Loading**

In your server file, add the import statement: `from dotenv import load_dotenv`. This imports the specific function we need for loading environment variables from our `.env` file.

Next, call `load_dotenv()` near the top of your file, after your imports but before you attempt to access any environment variables. This function reads your `.env` file and makes all defined variables available to your Python application through the operating system's environment.

Replace your hard-coded API key with: `openai_api_key = os.getenv('OPENAI_API_KEY')`. This retrieves the value associated with the `OPENAI_API_KEY` key from your environment variables. Notice that we're passing the key name as a string—this is because environment variables are stored as key-value pairs, and we're referencing the key to retrieve its associated value.

**Understanding Environment Variables**

Environment variables differ fundamentally from standard Python variables. While Python variables exist only within your script's execution context, environment variables are managed by the operating system and persist across different processes and applications. They're stored as string-based key-value pairs and provide a secure method for applications to access configuration data without embedding it directly in source code.


Let's test our implementation. Stop your current server instance (Ctrl+C) and restart it with `python server03.py`. Navigate to your application in the browser and verify that all functionality remains intact. If everything works correctly, your API key is now securely loaded from the environment rather than exposed in your source code.

**Addressing Previous Lesson Improvements**

Before we conclude, let's address a user experience issue from our previous lesson. Currently, when users switch between different food items for analysis, the previous meal's analysis text remains visible until the new analysis completes. This creates a confusing interface where users see outdated information.

The solution is straightforward: clear the analysis results immediately when a new image is loaded, rather than waiting for the new analysis to complete. In your JavaScript file, within the image loading function, add code to clear the `innerHTML` of your three result elements by setting them to empty strings.

Using `innerHTML` rather than `textContent` ensures we clear any HTML tags or entities that might be present in the results. This approach handles complex content gracefully and provides a cleaner user experience.

After implementing this change, refresh your application and test the behavior. You'll notice that selecting a new image immediately clears the previous analysis, providing users with clear visual feedback that new processing is beginning.

**Looking Ahead**

Our next enhancement addresses another user experience consideration: the delay between initiating analysis and receiving results. Currently, users may wait several seconds without any indication that processing is occurring, leading to uncertainty about whether their request was received.

In lesson 16, we'll implement a professional loading spinner using advanced CSS animations combined with JavaScript state management. This addition will provide users with clear visual feedback during processing, significantly improving the perceived performance of our application.

You've now mastered a critical security practice that's essential for any production application. Environment variable management isn't just about API keys—it's a fundamental approach to configuration management that you'll use throughout your career as a developer. See you in the next lesson where we'll enhance user experience with dynamic loading indicators.


Key Takeaways

1Hard-coding API keys in source files creates serious security vulnerabilities that can lead to unauthorized access and billing issues
2Environment variables stored in .env files keep sensitive data separate from your codebase and out of version control
3The Python-dotenv package enables easy loading of environment variables from .env files using the load_dotenv() function
4Use os.getenv() with quoted key names to access environment variables, as they exist as key-value pairs rather than regular Python variables
5Always check if packages are already installed using 'pip show package-name' before installing new dependencies
6Comment out hard-coded values initially rather than deleting them, allowing easy rollback if the environment variable setup fails
7Environment variables follow the format VARIABLE_NAME=value without quotes or spaces around the value in the .env file
8This security practice extends beyond API keys to include database passwords, tokens, and any other sensitive configuration data

RELATED ARTICLES