Python 3 区分生产和开发配置的最佳实践

Kme*_*low 5 python

我正在开发一个嵌入式系统项目,我的dev设置与我的prod. 差异包括变量和包导入。

为 python3 应用程序构建配置文件的最佳方法是什么,其中devprod设置不同?

prod:我的设备与电子系统交换消息(使用pyserial)并与服务器通信。

dev:我使用来自函数的虚假和固定响应来模拟电子和服务器响应。即使我模拟的功能在prod它们中是必不可少的,但在dev. 我可以嘲笑它们,因为这个项目最重要的部分是使用和处理它们的函数。因此,有些包导入和函数调用没有意义并在dev模式中引入错误。

每次我需要从一个切换到另一个时,我都需要更改大量代码,有时会引入错误。我知道这真的 () 不是最好的方法,我想知道什么是最佳实践

找到的最接近的解决方案

这里有一个很好的解决方案,可以为每个环境设置不同的变量。我希望有类似的东西,但对于需要为不同环境导入不同包的项目。

我的设置

基本工作流程:

  • task每秒执行一个线程
    • module_1 工作和打电话 module_2
    • module_2 工作和打电话 module_3
    • module_3 做工作并发回响应

基本文件夹结构:

  • root
    • main
    • config.py
    • /config
      • prod
      • dev
    • /mod_1
    • /mod_2
    • /mod_3
    • /replace_imports

module_1module_3使用,每个,一个特定的包prod,必须由一个dev函数替换

我有什么:

# config.py
if os.environ["app"] == "dev":
    import * from root.config.dev
if os.environ["app"] == "prod":
    import * from root.config.prod
Run Code Online (Sandbox Code Playgroud)
# config/prod.py
import _3rd_party_module_alpha
import _3rd_party_module_beta
...
obj_alpha = _3rd_party_module_alpha()
func_beta = _3rd_party_module_beta()
Run Code Online (Sandbox Code Playgroud)
# config/dev.py
import * from root.replace_imports
Run Code Online (Sandbox Code Playgroud)
# replace_imports.py
obj_alpha = fake_3rd_party_module_alpha()
func_beta = fake_3rd_party_module_beta()
Run Code Online (Sandbox Code Playgroud)

JL *_*ret 5

你真的不应该在 X 点的开发和推入 QA/CI 之间进行代码更改,然后在 X 点进行生产。当然,你的开发和生产代码在不同阶段可能会有所不同,版本控制是关键. 但是转移到生产不需要更改代码,只需要更改配置

环境变量(请参阅12 因素应用程序内容)可以提供帮助,但有时配置在代码中,例如在 Django 设置文件中。

在像 Django 这样“它指向”设置文件的环境中,我见过这样的东西:

base_settings.py:

common config
Run Code Online (Sandbox Code Playgroud)

dev_settings.py:

#top of file
import * from base_settings


... dev specifics, including overrides of base...
Run Code Online (Sandbox Code Playgroud)

编辑:我很清楚import *. 首先,这是一种特殊情况,对于配置,您导入所有内容。其次,真正的问题import *是它破坏了当前的命名空间。该导入就在顶部,因此不会发生。除了 Linter 之外,它们可以仅在该行中被抑制,剩下的问题是您可能并不总是知道变量神奇地来自哪里,除非您查看 base。

prod_settings.py:

import * from base_settings

...production specifics, including overrides of base...
Run Code Online (Sandbox Code Playgroud)

webpack 配置文件的高级用户(那些是残酷的)做同样的事情,即使用base.js然后将其导入dev.jsprod.js

这里的关键是在base中尽可能多地使用环境变量(注意不要过度依赖这些,没有人喜欢具有数十个环境变量设置的应用程序)。然后devprod基本上是关于键、路径、url、端口之类的东西。但是,请确保对它们保密,因为它们自然而然地被吸引到那里,但没有受到版本控制的业务。

关于。您当前的代码

appname = os.getenv("app")

if appname == "dev":

    #outside of base=>dev/prod merges, at top of "in-config" namespaces, 
    #I would avoid `import *` here and elsewhere

    import root.config.dev as config

elif appname == "prod":

    import root.config.prod as config

else:
    raise ValueError(f"environment variable $app should have been either `dev` or `prod`. got:{appname}:")


Run Code Online (Sandbox Code Playgroud)

最后,如果您没有“它指向 Python 设置文件”机制,类似于在 Django 中找到的机制,您可以(可能)通过将配置模块路径 ( xxx.prod, xxx.dev)存储在环境变量中,然后使用动态导入。请注意,您当前的代码在很大程度上已经做到了这一点,只是您无法试验/添加其他设置文件。

如果您没有立即得到它,请不要担心,也不要预先过度设计 - 需要一段时间才能找到最适合您/您的应用程序的方法。


bru*_*ers 3

使用 git 分支(或 Mercurial 或您正在使用的任何版本控制系统 - 您正在使用 vcs,是吗?)和 virtualenvs。这正是他们的目的。您的配置文件应该仅用于数据库连接标识符、API 密钥等内容。