影刀RPA 测试环境与生产环境的配置切换方案作者林焱什么情况用这个你辛辛苦苦在本地调试好的流程部署到服务器上后一堆问题测试时用的测试网站URL还在代码里、数据库连的是本地的、邮件发到了测试邮箱而不是客户的。一个个改过来吧——文件路径、数据库连接、API地址、通知接收人——几十个地方要改改完还怕漏了。职业的做法是流程设计时就区分测试和生产两套环境通过一个开关切换。改一个变量所有配置自动切过去。这篇文章给你一套环境管理方案从最简单的变量开关到完整的配置文件体系。怎么做第一步最简方案——一个环境变量控制一切在影刀变量面板中定义一个全局变量ENV变量名: ENV 值: dev 开发/测试环境 → dev生产环境 → prod然后在每一个需要区分环境的Python节点中根据ENV的值选择不同的配置# 配置字典——所有环境相关配置都集中在这里CONFIG{dev:{base_url:https://test.example.com,api_url:https://test-api.example.com,db_host:192.168.1.100,db_name:test_db,db_user:dev_user,output_dir:D:/test_output,notify_email:devcompany.com,log_level:DEBUG,},prod:{base_url:https://www.example.com,api_url:https://api.example.com,db_host:10.0.1.50,db_name:prod_db,db_user:prod_user,output_dir:D:/prod_output,notify_email:opscompany.com,log_level:WARNING,}}# 从影刀变量面板读取 ENV在输入变量中声明# 然后选择对应环境的配置envENVifENVinCONFIGelsedev# 默认开发环境env_configCONFIG[env]print(f当前环境:{env})print(fAPI:{env_config[api_url]})第二步把配置抽到JSON文件中拼多多店群自动化报活动上架变量面板里的ENV好管但CONFIG字典写在代码里不方便修改。抽到JSON文件文件结构D:/rpa_config/ ├── config.dev.json # 开发环境 ├── config.test.json # 测试环境 └── config.prod.json # 生产环境config.dev.json{env:dev,base_url:https://test.example.com,api:{base_url:https://test-api.example.com,timeout:30,max_retry:3},database:{type:mysql,host:192.168.1.100,port:3306,name:test_db,user:dev_user},paths:{input:D:/test_data/input,output:D:/test_data/output,log:D:/test_data/logs},notification:{email_to:[devcompany.com],wecom_webhook:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keytest,dingtalk_webhook:},features:{send_notification:false,backup_before_process:true,detailed_logging:true}}读取配置的通用函数importjsonimportosclassConfigLoader:配置加载器def__init__(self,config_dirD:/rpa_config):self.config_dirconfig_dir self.config{}defload(self,envdev):加载指定环境的配置config_fileos.path.join(self.config_dir,fconfig.{env}.json)ifnotos.path.exists(config_file):raiseFileNotFoundError(f配置文件不存在:{config_file})withopen(config_file,r,encodingutf-8)asf:self.configjson.load(f)print(f已加载配置:{config_file})print(f 环境:{self.config.get(env)})print(f API: {self.config.get(api, {}).get(base_url)})returnself.configdefget(self,key_path,defaultNone): 用点号路径获取配置值 如: config.get(api.timeout) → 30 config.get(database.host) → 192.168.1.100 keyskey_path.split(.)valueself.configforkeyinkeys:ifisinstance(value,dict):valuevalue.get(key)else:returndefaultreturnvalueifvalueisnotNoneelsedefault# 在影刀流程中使用 # 第一个Python节点configConfigLoader()config.load(ENV)# ENV从影刀变量读取# 后续节点中到处使用api_urlconfig.get(api.base_url)db_hostconfig.get(database.host)output_dirconfig.get(paths.output)should_notifyconfig.get(features.send_notification,False)第三步敏感信息与普通配置分离数据库密码、API密钥等敏感信息不能放在JSON文件中那些文件可能会提交到Git。单独管理// config.prod.json不含敏感信息{database:{host:10.0.1.50,port:3306,name:prod_db,user:prod_user// 密码在secrets中},api:{base_url:https://api.example.com,// key在secrets中}}// secrets.prod.json敏感信息不提交Git{database:{password:实际密码},api:{api_key:sk-实际密钥}}defload_full_config(env):加载完整配置合并公开配置和敏感配置configConfigLoader()base_configconfig.load(env)# 尝试加载敏感配置secrets_fileos.path.join(config.config_dir,fsecrets.{env}.json)ifos.path.exists(secrets_file):withopen(secrets_file,r,encodingutf-8)asf:secretsjson.load(f)# 深度合并敏感信息覆盖基础配置deep_merge(base_config,secrets)print(f已加载敏感配置:{secrets_file})else:print(f未找到敏感配置文件:{secrets_file})returnbase_configdefdeep_merge(base,override):深度合并两个字典forkey,valueinoverride.items():ifkeyinbaseandisinstance(base[key],dict)andisinstance(value,dict):deep_merge(base[key],value)else:base[key]value第四步数据库连接的环境切换importpymysqldefget_db_connection(config):根据配置创建数据库连接db_config{host:config.get(database.host),port:config.get(database.port,3306),user:config.get(database.user),password:config.get(database.password),database:config.get(database.name),![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/91d2ebd84ca04f0aba540c5df121b512.png#pic_center)charset:utf8mb4,}# 测试环境可能不需要密码ifnotdb_config[password]:db_config.pop(password,None)returnpymysql.connect(**db_config)第五步不同环境的行为差异不光数据不同行为也可以不同# 根据环境决定是否发送真实通知ifconfig.get(features.send_notification):send_wecom_alert(流程完成)else:print(f[{env}] 跳过通知发送当前环境不发送通知)# 根据环境决定是否备份原始数据ifconfig.get(features.backup_before_process):backup_file(source_path)# 根据环境决定日志详细程度log_levelconfig.get(log_level,INFO)有什么坑坑一生产代码中残留测试配置现象部署到生产后URL还在调测试网站的API生产数据写到了测试数据库。解决在配置文件中加一个env字段做自检# 启动时验证env_nameconfig.get(env)ifenv_nameprod:# 确保几个关键配置不是测试环境的asserttestnotinconfig.get(api.base_url,),\生产环境不能使用测试API地址assertconfig.get(features.send_notification),\生产环境必须开启通知坑二JSON配置文件写了注释导致解析失败现象在JSON里加了// 这是注释加载时报JSON格式错误。TEMU店群矩阵自动化运营核价报活动原因标准JSON不支持注释。解决要么用不写注释的JSON要么改用YAML或TOML格式。但最省事的方法是用字段名做自解释{api_base_url_comment:API服务器地址生产环境为 https://api.example.com,api_base_url:https://api.example.com}坑三不同环境文件路径不一致现象开发环境路径是D:/project/data/生产是E:/app/data/忘了改。解决配置中的路径用环境变量或相对路径{paths:{data_root:D:/rpa_data,input:${data_root}/input,output:${data_root}/output}}坑四多台机器共用配置文件现象配置文件在所有机器上都是一样的但每台机器的磁盘分区不同。解决配置文件里写相对路径或使用目录引用机器级别的差异放在环境的系统变量中。坑五修改配置后没有立即生效现象改了config.json流程还是用的老配置。原因配置是在流程启动时加载一次长流程运行期间不会重新读取。解决每天晚上重新启动一次流程用系统的计划任务或者在每个循环开始时重新读取配置。总结环境管理不是为了好看是为了避免在测试环境跑了三个月没问题一上生产全崩的灾难。最低成本的做法定义一个ENV变量所有的URL、路径、邮箱都用这个变量来选择。一劳永逸的做法用JSON配置文件 ConfigLoader新项目直接复制这套模板。