折腾:
【未解决】Flask中如何利用环境变量实现自动加载开发还是生产的配置
期间,经过调试:
另外,再去改为之前的代码:
app.config.from_object('config.DevelopmentConfig') # app.config.from_object('config.ProductionConfig') print("for debug: after load from config.DevelopmentConfig: app.config=%s" % (app.config)) # app.config.from_object(settings) # print("for debug: after load from settings: app.config=%s" % (app.config))
看看输出结果是不是完全一样 -》 以确保此处的config是和之前的方式的效果是一样的,没有其他不良影响
结果发现了还是有点点影响的:
即:
从settings中导入的值,都是字符串:
之前的:
DEBUG=True
变成了:
‘DEBUG’: ‘True’,
而不是希望的:
‘DEBUG’: True,
发现:
从.env中用
os.getenv
加载的int的配置
都只是字符串,而不是原始的配置的类型的值
比如int,bool等
-》那再去故意弄一些,其他类型,比如数字,看看是否也是字符串
DEMO_INT = 1000 DEMO_COMPLEX_INT = 2 * 10
果然还是字符串:
所以现在问题来了:
希望从settings中加载的变量,都可以转换为特定的类型,比如bool,int等等
感觉像是:
每个变量,手动类型转换?
或者是从ini等配置文件中,加载变量,自动判断类型?
不过突然觉得又好像不现实:
貌似即使从.env的int得到了要的变量的类型,而此处从
os.getenv
得到的变量,好像也只能是字符串吧?
所以去搜搜看
os.getenv get variable type
python os get environment keep type
看来只能去手动强制转换变量的原始类型了
“os.getenv(key, default=None)
Return the value of the environment variable key if it exists, or default if it doesn’t. key, defaultand the result are str.”
官网说了:os.getenv只是返回字符串
所以只能自己手动转换类型了。
所以改为:
# DEBUG = os.getenv("DEBUG") DEBUG = bool(os.getenv("DEBUG")) MONGODB_HOST = os.getenv("MONGODB_HOST") FILE_URL_HOST = os.getenv("FILE_URL_HOST") # DEMO_INT = os.getenv("DEMO_INT") # DEMO_COMPLEX_INT = os.getenv("DEMO_COMPLEX_INT") DEMO_INT = int(os.getenv("DEMO_INT")) DEMO_COMPLEX_INT = int(os.getenv("DEMO_COMPLEX_INT"))
结果
但是复杂的数字的表达式,就不支持了:
DEMO_COMPLEX_INT = int(os.getenv("DEMO_COMPLEX_INT")) ValueError: invalid literal for int() with base 10: '2 * 10'
所以为了避免歧义,则:
【总结】
.env中:
- 最好全部都改为字符串
- 且都是简单的值
- 不要写数字的表达式,比如 2 * 60 * 60
举例如下:
;DEBUG = True DEBUG = "True" # for local dev, need access remote mongodb MONGODB_HOST = "xxx" FILE_URL_HOST = "127.0.0.1" DEMO_INT = "1000" ;DEMO_COMPLEX_INT = 2 * 10
然后settings中,先os.getenv获取字符串,再调用类型转换,int(),bool()等,去转换为自己需要的值
DEBUG = bool(os.getenv("DEBUG")) MONGODB_HOST = os.getenv("MONGODB_HOST") FILE_URL_HOST = os.getenv("FILE_URL_HOST") DEMO_INT = int(os.getenv("DEMO_INT")) # DEMO_COMPLEX_INT = int(os.getenv("DEMO_COMPLEX_INT")) print("After load .env: DEBUG=%s, MONGODB_HOST=%s, FILE_URL_HOST=%s, DEMO_INT=%s" % (DEBUG, MONGODB_HOST, FILE_URL_HOST, DEMO_INT))
算是基本上满足了此处的需求了:
输出对应类型的数据了:
【后记】
发现直接判断False或True的字符串,是不正确的,因为:
bool("False") -> True
所以要去改为:
# DEBUG = os.getenv("DEBUG") # DEBUG = bool(os.getenv("DEBUG")) debug_str = os.getenv("DEBUG") if debug_str: debug_str_lower = debug_str.lower() if (debug_str_lower == "false") or (debug_str_lower == "0"): DEBUG = False elif (debug_str_lower == "true") or (debug_str_lower == "1"): DEBUG = True