首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中处理dev/test/prod变量的最佳方法?

在Python中处理dev/test/prod变量的最佳方法?
EN

Software Engineering用户
提问于 2017-02-23 04:33:28
回答 3查看 23.8K关注 0票数 9

我正在创建一个python模块,并且我有一个配置文件,其中包含的变量用于dev或prod (即S3存储桶)。做这件事最好的方法是什么?现在,我在配置中使用了DEV或PROD选项,但是每次在类中选择这个选项似乎很乏味(例如,S3_BUCKET、开发人员等)。

EN

回答 3

Software Engineering用户

发布于 2017-02-23 05:17:09

当您根据环境需要不同的值时,您可以依赖以下几点:

  • 命令行参数,如--db-path=...
  • 系统环境变量,如$MYAPP_DB_PATH
  • 一个固定路径的本地文件(在unix系统上,它们通常位于/etc)。

通常,我选择一个固定路径的本地文件,它们在程序中更容易处理,并且可以很容易地扩展。以后还可以通过命令行或系统环境变量来灵活地指定该文件的路径。该文件应包含逻辑环境的变量。您运行的代码不应该知道它在哪个环境中运行,因为这意味着您无法测试您的生产代码(这是一个非常糟糕的想法)。

这是一个一般的建议,并不是通常与Python绑定的,但这是一个示例,说明您将如何在该语言中使用简单的方法(我并不真正了解S3桶,我将只使用普通的json文件以达到清晰的目的):

Code.py:

代码语言:javascript
复制
import json
with open('mycfg.json') as f:
    env_vars = json.loads(f.read())
do_something(env_vars)

mycfg_dev.json:

代码语言:javascript
复制
{
    "path": "/tmp",
    "ip": "127.0.0.1",
    "login": "root",
    "password": "root"
}

mycfg_prod.json:

代码语言:javascript
复制
{
    "path": "/var/www",
    "ip": "192.168.1.44",
    "login": "myapp",
    "password": "aunriseqvoa"
}

您可以在某个地方对这两个文件进行版本化,必要时对其进行加密(例如在可承受保险库中)。非常小心,不要在你的回购中背诵纯文本生产凭证,因为以后很难从git中删除它。

部署时,只需在运行模块时重命名所需的模块,或根据实现将其提供给run命令。注意,如果这是实际的话,cfg文件可以重定向到另一个数据容器(如S3),如果它比普通文件具有任何优势。

一般来说,这就是我处理环境变量的方式,但也许我理解了您的需求方面的一些错误。

票数 8
EN

Software Engineering用户

发布于 2019-08-30 20:26:45

我在基于Node.js的大型企业应用程序上工作。但我认为,方法可以是一样的:

config/default.py配置。在这里,您可以定义独立于env的公共变量。例如:

config/default.py

代码语言:javascript
复制
config = {
    'app_name': 'Spotify',
    'jobs_num': 2,
    'host': 'localhost',
    'port': 3000
}

然后,您就可以对特定的环境拥有特定的信任。

config/production.py

代码语言:javascript
复制
config = {
    'host': 'myapp.com'
}

config/development.py

代码语言:javascript
复制
config = {
    'app_name': 'Spotify',
    'jobs_num': 3,
    'host': 'localhost',
    'port': 3001
}

然后,我更希望env.py配置具有下一个内容:

env.py

代码语言:javascript
复制
def get_env(var, default=None):
    return os.environ[var] or default

config = {
    'app_name': get_env('APP_NAME'),
    'jobs_num': get_env('JOBS_NUM'),
    'host': get_env('HOST'),
    'port': get_env('PORT')

main:config/config.py,应该总是导入,而不是env特定的配置:

config.py

代码语言:javascript
复制
from default import config as default_config
from development import config as dev_config
from production import config as prod_config
from env import config as envs

environment = os.environ['PYTHON_ENV'] or 'development'
environment_config = None
if environment == 'development':
    environment_config = dev_config
if environment == 'production':
    environment_config = prod_config

def chain_configs(*config_items): 
    for it in config_items: 
        for element in it: 
            value = element[1] 
                if value is not None: 
                    yield element 

### from python3.5

config = dict(chain_configs(*default_config.items(), environment_config.items, envs.items()))

这段代码还有下一个好处

  • 您可以将通用变量粘贴到文件中。
  • 信任是常规的.py文件,因此您可以向它们添加动态表达式(如果需要)
  • 您不受环境文件的限制,可以在开始时通过指定env变量来更改应用程序。例如:PYTHON_ENV=production JOBS_NUM=3 python server.py
  • 您的应用程序在代码中不知道它是什么环境--它是一个很好的抽象。
  • 明确的优先事项:环境变量是主要的。然后转到env特定配置,然后默认配置。

缺点:

  • 也许,过载的production方式。与小脚本相比,我更喜欢常规环境变量。
  • chain_configs并不完美,因为它没有处理深度字典。
  • 指定仅在env.py中指定的env变量的能力
票数 7
EN

Software Engineering用户

发布于 2017-02-23 06:07:05

从您的评论中可以看出,您的情况之一是,您的属性通过dev和prod保持一致,您不想重复。解决这一问题的一种方法是让这个阶段(dev或prod)成为您的键的一部分,并使用通配符拥有相同的键。例如

代码语言:javascript
复制
dev.s3bucket = "dev-bucket";
prod.s3bucket = "prod-bucket";
*.csvfile = "report.csv";

(您可以根据不同的配置格式调整此方法)。然后编写一个简单的配置管理器,您可以请求"s3bucket“,它会为您的环境查找适当的值。

这种方法的好处是,如果您添加了另一个环境,或者您想在配置中添加一个完全不同的参数,比如在不同区域运行时有不同的资源,那么它就很容易扩展。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/342788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档