Hardcoding API keys in your scripts is a bad idea:
it shows you are not aware of basic safety best practices,
or that you just don’t care about safety (you should),
and you can potentially leak sensitive information (just like it happened to Rabbit).
All in all, storing API keys safely is not a nice-to-have, but a must.
So let’s see how.
How to use your API keys safely in Python
On a high-level, this is what you’re gonna learn:
Define your API key in a file called
.env
that only you have access to.Use the
python-dotenv
library to load your API key from.env
so that your code can use your API key, but not see it (=safety).Run your code, be happy. 😊
Yep, it’s that easy. Let’s check out the actual code.
First, create a .env
file somewhere in your project folders (yes, the “.” is required).
(For extra safety, add .env
to your .gitignore
file too.)
Add your API key to your .env
file (or any environment variables that you want to keep secret).
In this example, I’ll use an Anthropic API key, because there’s a world besides OpenAI:
ANTHROPIC_API_KEY=totally-made-up-API-key-value-pls-create-your-own
As you can see, no ‘ or “ is required, because the values in .env
are treated as strings.
So this works perfectly too:
ANTHROPIC_API_KEY='totally-made-up-API-key-value-pls-create-your-own'
Or this:
ANTHROPIC_API_KEY="totally-made-up-API-key-value-pls-create-your-own"
Let’s grab the python-dotenv library:
pip install python-dotenv
(Yes, it’s called python-dotenv
, not dotenv
; it always confuses me a bit, because in scripts we import from dotenv
. Guess we’ll have to deal with it. 🙂)
Then import load_dotenv:
from dotenv import load_dotenv
load_dotenv
provides access to the environment variables defined in .env
.
To actually access the environment variables’ values, we need the os
library:
ANTHROPIC_API_KEY = os.getenv(“ANTHROPIC_API_KEY”)
You can check if it worked:
print(ANTHROPIC_API_KEY)
You should see this as the output:
It seems to have worked; you are A_MA_ZING! 😎
Now you know how you can safely load secret stuff in Python.
Hey, you want a quick tip? 😉 (If no, jump to the next section.)
The best way to write the values in the .env
file is to either use ‘ or nothing like this:
ANTHROPIC_API_KEY='totally-\nmade-up-API-key-value-pls-create-your-own'
Or this:
ANTHROPIC_API_KEY=totally-\nmade-up-API-key-value-pls-create-your-own
The reason for this is that this way the value will be treated as a string literal, so special characters won’t mess up your string; it’ll remain the way you defined it.
To demonstrate what happens using ‘ or nothing around the string, I put a \n
in the original string. This is the result in both cases:
But if you use “ like here:
ANTHROPIC_API_KEY="totally-\nmade-up-API-key-value-pls-create-your-own"
Then the special character (\n
) will be executed, and it’ll mess up your string (=your code can’t use your API key, because it’ll receive a faulty one):
So this is something to keep in mind.
Now let’s move on to an actual code where your freshly gained .env
knowledge comes in handy.
Make a large language model call with the help of dotenv
In this example, we save an Anthropic API key in a .env
file, then use it to instruct a LLM to translate a sentence into Italian.
This is the full code (I took the LLM part from an official LangChain tutorial):
# There's a reason the imports are in this order.
import os
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.output_parsers import StrOutputParser
# This is (part of) what you learned in this article.
load_dotenv()
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
# This is the fancy part, because of – you know – LLMs.
model = ChatAnthropic(model="claude-3-sonnet-20240229")
messages = [
SystemMessage(content="Translate the following from English into Italian"),
HumanMessage(content="Hope you have an awesome day!"),
]
parser = StrOutputParser()
chain = model | parser
print(chain.invoke(messages))
If you actually want to run the code, you’ll have to create an Anthropic account.
But you don’t have to do that for now – the point of the above code is to show you a real-life example where reading a variable from a .env
file is used.
(If you’re interested, here’s a project of mine where I used .env
for email credentials).
From now on, loading API keys safely should mean no issue for you.
Isn’t that cool? 👏
Apparently there is a ridiculous amount of API keys and other secret keys 🔑 just lying around public GitHub repositories 🫠
This should help people stay safe!