在工作中会出现这么一种需求,就是在一个配置文件中,希望可以根据某个条件动态处理文本,大佬已经写好了,感觉挺难明白的,根据自己的思路,自己写了一个。
比如:
xxxxx
##if {{xx}}
xxxx
##else
yyyy
##endif
mmmmmm
##if {{aa}}
aaaa
##else
bbbbb
##endif
满足xx条件的时候保留xxxx,满足aa保留aaaa 去掉bbbb,这个功能挺简单,却挺实用
def my_loader(path,vars=[]):
with open(path, 'r') as f:
content=f.read().split('\n')
go=True
rc=''
for line in content:
print(line[line.find(' ')+1:])
if line.startswith("##if") and judge(line[line.find(' ')+1:],vars):
go=True
continue
elif line.startswith("##if") and not judge(line[line.find(' ')+1:],vars):
go = False
continue
if line.startswith("##else"):
go = not go
continue
if line.startswith('##endif'):
go=True
continue
if not line.startswith('##') and go:
line=line+'\n'
rc=rc+line
print(rc)
def judge(var,vars):
if var in vars and vars[var]:
return True
else:
return False
if __name__=='__main__':
path="/root/naduo/ylai-deploy/deploy/generator/template/units/service/ap.template.yaml"
vars={'{{redis.ha}}':False,"{{ap.kube}}":True}
my_loader(path,vars)
处理的配置文件
config:
metrics_port: "{{++5:resource.ports.metrics}}"
services:
$name:
image: registry.cn-beijing.aliyuncs.com/yunli_ai/algo-platform:$tag
environment:
- JAVA_OPTS=-Dspring.datasource.url=jdbc:mysql://{{mysql.host}}:{{mysql.port}}/{{mysql.db}}?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
-Dspring.datasource.username={{mysql.user}}
-Dspring.datasource.password={{mysql.password}}
##if {{redis.ha}}
-Dspring.redis.cluster.max-redirects=3
-Dspring.redis.cluster.nodes=[[,|redis@{{host}}:{{port}}]]
##else
-Dspring.redis.host={{redis.host}}
-Dspring.redis.port={{redis.port}}
##endif
-Dspring.redis.timeout=30000
-Dspring.redis.password={{redis.password}}
-Dyunli.algo.atomicapi.video-server={{video.host}}:{{video.port}}
-Dyunli.algo.atomicapi.face-api-server={{faceapi.host}}:{{faceapi.port}}
##if {{ap.kube}}
-Dyunli.dispatch.url=https://{{kubernets.host}}:{{kubernets.port}}
-Dyunli.dispatch.gpus={{resource.gpu}}
-Dyunli.dispatch.key=/config/server.pfx
-Dyunli.dispatch.type=kubernetes
##else
-Dyunli.dispatch.url=https://{{docker.host}}:{{docker.port}}
-Dyunli.dispatch.gpus={{resource.gpu}}
-Dyunli.dispatch.key=/config/server.pfx
-Dyunli.dispatch.type=docker
##endif
volumes:
##if {{ap.kube}}
- "@config():/config"
##else
- "{{deploy_dir}}/ap/log:/log"
- "{{deploy_dir}}/ap/@config():/config"
##endif
labels:
- "dispatch_platform=ap"
ports:
- $port:4080
- "$metrics_port:9090"
处理后的文件
config:
metrics_port: "{{++5:resource.ports.metrics}}"
services:
$name:
image: registry.cn-beijing.aliyuncs.com/yunli_ai/algo-platform:$tag
environment:
- JAVA_OPTS=-Dspring.datasource.url=jdbc:mysql://{{mysql.host}}:{{mysql.port}}/{{mysql.db}}?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
-Dspring.datasource.username={{mysql.user}}
-Dspring.datasource.password={{mysql.password}}
-Dspring.redis.host={{redis.host}}
-Dspring.redis.port={{redis.port}}
-Dspring.redis.timeout=30000
-Dspring.redis.password={{redis.password}}
-Dyunli.algo.atomicapi.video-server={{video.host}}:{{video.port}}
-Dyunli.algo.atomicapi.face-api-server={{faceapi.host}}:{{faceapi.port}}
-Dyunli.dispatch.url=https://{{kubernets.host}}:{{kubernets.port}}
-Dyunli.dispatch.gpus={{resource.gpu}}
-Dyunli.dispatch.key=/config/server.pfx
-Dyunli.dispatch.type=kubernetes
volumes:
- "@config():/config"
labels:
- "dispatch_platform=ap"
ports:
- $port:4080
- "$metrics_port:9090"
附上大佬写的语法,
def macro_loader(fname, targets={}):
with open(fname, 'r') as f:
cont = f.read().split('\n')
print('replace for '+fname)
rb = None
drop_mask = False
already_hit = False
mask_stack = []
ah_stack = []
for line in cont:
if line.startswith('##if '):
# enter deep stack
mask_stack.append(drop_mask)
ah_stack.append(already_hit)
drop_mask = False
already_hit = False
if line.startswith('##if ') or line.startswith('##elif'):
if already_hit:
drop_mask = True
else:
try:
if eval(str(str_fill(line[line.find(' ')+1:], targets))):
judge_res = True
else:
judge_res = False
except:
# regard exception as condition fail
judge_res = False
if judge_res:
already_hit = True
drop_mask = False
else:
drop_mask = True
elif line.startswith('##else'):
if already_hit:
drop_mask = True
else:
drop_mask = False
elif line.startswith('##endif'):
drop_mask = mask_stack.pop()
already_hit = ah_stack.pop()
else:
cnd = not drop_mask
for outer_mask in mask_stack:
cnd = cnd and not outer_mask
if cnd:
if rb is None:
rb = ''
else:
rb = rb + '\n'
rb = rb + line
return rb