This are some notes around the use of secrets.py in CircuitPython.
Today CP examples suggest a secrets.py
files for storing passwords, SSIDs, keys, etc as a dictionary.
File: secrets.py
secrets = {
key = value,
key1 = value1
}
Usage of this looks like so:
from secrets import secrets
print(secrets['key'])
- Secrets is a core module in Python, so we're teaching new coders a practice which will surely leads to confusion if\when they move on to Python coding.
- Using a dictionary is not wrong, but combersome and lacks the helpful functionality other approaches would have, such as autocomplete.
At a minimum, suggesting the use of secrets.py should be changed. The good thing about that name though is that it does imply that it is information you don't want to put into your GitHub repo. Some potential new file names:
- config.py <-- This could be for all configuraion you can commit.
- config_secrets.py <-- this could be for all configuration you should NOT commit.
Adding config.secrets.py to the .gitignore should also be recommended and added to .gitignore tools.
Question: Should the recommendation also be use the CAPS style since these are truly globals? ex:
config_secrets.KEY1
The dictionary format could be improved. Using variables would allow for dot notation and autcomplete.
file: config_secrets.py
key = value
key1 = value1
file: code.py
import config_secrets.py
print(config_secrets.key1)
In CPython, it is common to use OS environment variables and the OS Core Module to work with the values:
- os.get_env:
os.getenv(key, default=None)
returns the value of the environment variable or the supplied default. - os.environ:
Tuple-like string mapping of environment variables at thetime of os import.
Updating the object also updates the environment and is preferred to calling
os.putenv
oros.unsetenv
directly. - os.putenv: Creates or updates an evironment variable, does not update os.environ.
- os.unsetenv: Deletes an environment variable, does not update os.environ
- os.environb:
Bytes version of
os.environ
. Linux Only - os.get_envb:
Bytes version of
os.get_env
. Linux Only
os.get_env()
is the very common method usesin CPython applications.
There are also many environment libraries for CPython and frameworks (Django, ertc..) to help manage not only run-time but dev, test, production environments.
In MicroPython there is nothing implemented in the MP core libraries. There is an external library ShenTengTu/micropython-env which doesn't appear to be in wide use (2 ⭐️). The approach in ShenTengTu/micropython-env is to import from JSON files or MessagePack
- It was suggested by @tannewt, that CP could use an approach similiar to the environment variable approach. How these are set initially is still an unknown to me. I could see os.put_env() being called from the REPL or from boot.py to set values from config_secrets.py. for example:
os.load_env(config_secrets)
and then usingos.get_env()
. - Are values preserved across reboots is an interesting discussion...
I just stumbled across this the other day. I'm new to CP, but not to Python. I think "training" people from the start to not use a filename that's likely to conflict with something in the standard library is a really smart change. Especially since CP is targeting beginners, having a random name collision is not great.
Of the options you present for changing the contents of the file, just making things be global module variables seems the most Pythonic. The import statement is straightforward and keeping the format simple and readable seems like a win. Loosing the ability to use a default in
os.get_env()
does seem like a minor loss, but I don't think this is as valuable as keeping the syntax and process simple.This is effectively embedded Python. Complicating things with having to
os.load_environ()
and useos.get_env()
seems way overkill. Just being able to referenceconfig_secrets.NASA_API_KEY
is simple and easier for a beginner to understand.Just to be clear, I don't think we should prohibit the use of other options, but for getting new/beginner programmers up and running with CP, a simple solution is probably best.