https://www.pydanny.com/using-executable-code-outside-version-control.html
开发世界现在有很多反设计模式的开发方式,比如使用可执行代码作为配置文件。
在Python世界里面,你很可能碰到过类似下面的代码:
# 警告:这是反模式代码!
try:
from .local_settings import *
except ImportError:
pass
一般来说,人们会在local_settings.py
文件中加入一些配置变量,然后加入到.gitignore
里面。因此,本地开发环境,你的项目需要一个脱离版本控制的可执行代码文件。
如果你觉得不对劲,那么你走在正确的道路上。可执行代码就应该总是处于版本控制中。
另一个更好的方式是,把secrets和key等配置放在环境变量里面。如果你不喜欢这种方式,或者因为环境的原因不可以这么做,仍然可以把配置放在JSON, YAML, TOML文件里面。
local_settings
这种反模式
说local_settings
是反模式,是因为你生产环境的可执行代码,不能被开发者看到,也让他们不好debug解决问题。可能你还没有这种体验,但这确实是最糟糕的调试噩梦之一。
它在我的笔记本上运行良好!
有时候,在开发和测试中没有发现一些细微的bug,发现的时候已经太晚了。
下面是一个真实的例子,来自于去年我帮客户解决的问题:
- 项目使用第三方库做slug。配置放在settings中。
- 开发者决定自己编写slug项目。在本地运行良好。
- 测试没有加入新的testcase,测试那些边角案例。
- 在本地开发环境,staging环境,甚至生产环境都看起来运行正常。
- 几天之后,一些特定地区的用户报告说,一些记录不可以访问。
- 没人知道为什么生产环境会出现这个问题。
然后我介入了。首先我就注意到,settings文件里面有下面这种代码:
# 警告:这是反模式代码!
try:
from .local_settings import *
except ImportError:
pass
他们在版本控制之外还有可执行代码。这也是为什么在开发环境有效,但是在其它环境有问题。即使这个微妙的bug,已经通过了常规的测试。但是,进入生产环境之后,这个bug就会被用户发现。
然后,最糟糕的是,这个bug在第一时间几乎不可能被发现,因为开发者的local_settings.py
的值是正确的。
但是我不会犯这种错误!
人们一般会气愤地说,“我不像你那么蠢,我不会犯这种错误。“
是的,最近20年我也只碰到去年这一次因为这个原因造成的bug。
但是我相信,不管程序员都没天才,多么有经验,都无可避免会犯一些愚蠢的错误。这是为什么一些好的程序员/工程师都会遵循一个很好的习惯 — 在犯了愚蠢错误的时候,能够快速捕获。如果你认为自己能够完全避免这种错误,我只能说你太年轻了。
回到正题,为什么一定要把配置放在可执行文件里?你可以将它们放在环境变量,或者配置文件。所以,争论结束!
如何处理环境特有变量
使用环境变量,或者配置文件!
你可以使用第三方库。我个人喜欢使用django中自带的功能.
import os
from django.core.exceptions import ImproperlyConfigured
def get_env_var(var_name):
try:
return os.environ[var_name]
except KeyError:
error_msg = f"Set the {var_name} environment variable"
return ImproperlyConfigured(error_msg)
SECRET_KEY = get_env_var('SECRET_KEY')