从另一个python文件编辑python文件的参数
我有一个包含dict的python文件形式的应用程序配置文件,我正在运行AWS lambda函数从S3获取此conf文件,更改其中的三个变量,然后将副本推回到S3。有没有简单的方法来做到这一点?一位同事说要尝试Jinja模板,但这似乎仅限于HTML文件?从另一个python文件编辑python文件的参数
由于
蟒配置文件的一个例子是下面。我需要改变 “阿尔法” 和 “循环” 变量
import zutil
alpha = 2.13
cycles = 100
def my_transform(x, y, z):
v = [x, y, z]
v = zutil.rotate_vector(v, alpha, 0.0)
return {'v1': v[0], 'v2': v[1], 'v3': v[2]}
parameters = {
# units for dimensional quantities
'units': 'SI',
# reference state
'reference': 'IC_1',
'time marching': {
'unsteady': {
'total time': 1.0,
'time step': 1.0,
'order': 'second',
},
'scheme': {
'name': 'lu-sgs',
'stage': 1,
#'name' : 'runge kutta',
#'stage': 5,
},
'lu-sgs': {
'Number Of SGS Cycles': 8,
'Min CFL': 0.1,
'Max CFL': 5.0,
'Include Backward Sweep': True,
'Include Relaxation': True,
'Jacobian Update Frequency': 1,
'Jacobian Epsilon': 1.0e-08,
'CFL growth': 1.05,
'Use Rusanov Flux For Jacobian': 'true',
'Finite Difference Jacobian': 'false',
},
'multigrid': 10,
'cfl': 2.5,
'cfl transport': 2.5 * 0.5,
'ramp': {'initial': 1.0, 'growth': 1.1},
'cycles': cycles,
},
'equations': 'RANS',
'RANS': {
'order': 'euler_second',
'limiter': 'vanalbada',
'precondition': 'true',
'turbulence': {
'model': 'sst',
},
},
'material': 'air',
'air': {
'gamma': 1.4,
'gas constant': 287.0,
'Sutherlands const': 110.4,
'Prandtl No': 0.72,
'Turbulent Prandtl No': 0.9,
},
'IC_1': {
'temperature': 310.928,
'pressure': 101325.0,
'alpha': alpha, # User defined variable used for post processing
'V': {
'vector': zutil.vector_from_angle(alpha, 0.0),
'Mach': 0.85,
},
'Reynolds No': 5.0e6,
'Reference Length': 275.8,
'turbulence intensity': 1.e-4,
'eddy viscosity ratio': 0.1,
},
'BC_1': {
'ref': 7,
'type': 'symmetry',
},
'BC_2': {
'ref': 3,
'type': 'wall',
'kind': 'noslip',
},
'BC_3': {
'ref': 9,
'type': 'farfield',
'condition': 'IC_1',
'kind': 'riemann',
},
'write output': {
'format': 'vtk',
'surface variables': ['V', 'p', 'T', 'rho', 'walldist', 'yplus', 'mach', 'cp', 'eddy', 'pressureforce', 'frictionforce'],
'volume variables': ['V', 'p', 'T', 'rho', 'walldist', 'mach', 'cp', 'eddy'],
'frequency': 500,
},
'report': {
'frequency': 10,
'forces': {
'FR_1': {
'name': 'wall',
'zone': [9, 10, 11, 12, 13],
'transform': my_transform,
'reference area': 594720.0 * 0.5, # half model area # half model area # half model area
},
},
},
}
Jinja2的肯定能做到这一点。但如果它是值得做的是另外一个问题
我修改你的文件一点点,使其渲染由Jinja2的
import zutil
alpha = {{ alpha | default(2.13) }}
cycles = {{ cycles | default(100)}}
def my_transform(x,y,z):
v = [x,y,z]
v = zutil.rotate_vector(v,alpha,0.0)
return {'v1' : v[0], 'v2' : v[1], 'v3' : v[2]}
parameters = {
# units for dimensional quantities
'units' : 'SI',
# reference state
'reference' : 'IC_1',
'time marching' : {
'unsteady' : {
'total time' : 1.0,
'time step' : 1.0,
'order' : 'second',
},
'scheme' : {
'name' : 'lu-sgs',
'stage': 1,
#'name' : 'runge kutta',
#'stage': 5,
},
'lu-sgs' : {
'Number Of SGS Cycles' : 8,
'Min CFL' : 0.1,
'Max CFL' : 5.0,
'Include Backward Sweep' : True,
'Include Relaxation' : True,
'Jacobian Update Frequency' : 1,
'Jacobian Epsilon' : 1.0e-08,
'CFL growth' : 1.05,
'Use Rusanov Flux For Jacobian' : 'true',
'Finite Difference Jacobian' : 'false',
},
'multigrid' : 10,
'cfl': 2.5,
'cfl transport' : 2.5*0.5,
'ramp': { 'initial': 1.0, 'growth': 1.1 },
'cycles' : cycles,
},
'equations' : 'RANS',
'RANS' : {
'order' : 'euler_second',
'limiter' : 'vanalbada',
'precondition' : 'true',
'turbulence' : {
'model' : 'sst',
},
},
'material' : 'air',
'air' : {
'gamma' : 1.4,
'gas constant' : 287.0,
'Sutherlands const': 110.4,
'Prandtl No' : 0.72,
'Turbulent Prandtl No' : 0.9,
},
'IC_1' : {
'temperature':310.928,
'pressure':101325.0,
'alpha': alpha, # User defined variable used for post processing
'V': {
'vector' : zutil.vector_from_angle(alpha,0.0),
'Mach' : 0.85,
},
'Reynolds No' : 5.0e6,
'Reference Length' : 275.8,
'turbulence intensity':1.e-4,
'eddy viscosity ratio':0.1,
},
'BC_1' : {
'ref' : 7,
'type' : 'symmetry',
},
'BC_2' : {
'ref' : 3,
'type' : 'wall',
'kind' : 'noslip',
},
'BC_3' : {
'ref' : 9,
'type' : 'farfield',
'condition' : 'IC_1',
'kind' : 'riemann',
},
'write output' : {
'format' : 'vtk',
'surface variables': ['V','p','T','rho','walldist','yplus','mach','cp','eddy','pressureforce','frictionforce'],
'volume variables': ['V','p','T','rho','walldist','mach','cp','eddy'],
'frequency' : 500,
},
'report' : {
'frequency' : 10,
'forces' : {
'FR_1' : {
'name' : 'wall',
'zone' : [9,10,11,12,13],
'transform' : my_transform,
'reference area' : 594720.0*0.5, # half model area # half model area # half model area
},
},
},
}
下面是如何使用Jinja2的渲染它。假设path_1是你的配置文件的路径。 PATH_2是新的配置文件的路径
from jinja2 import Environment, FileSystemLoader
new_config_contex = {'alpha':3, 'cycles': 200}
path, template_filename = os.path.split(path_1)
env = Environment(loader=FileSystemLoader(path))
new_conf_file_content=env.get_template(template_filename).render(new_config_contex)
with open(path_2, "wb") as f:
f.write(new_conf_file_content)
感谢您的建议,接受并延伸出我的回复,我张贴。 – Lewiky
我找到了解决办法,这不是漂亮和SRC所提到的,这是一个坏的解决方案,不应该在任何实际使用,但它的工作原理。
我从蜀黍了意见和转换我的参考control.py文件到神社模板如下所示:
import jinja2
from sys import argv
pyConf = """
import zutil
alpha = {{alpha}}
cycles = {{cycles}}
def my_transform(x,y,z):
v = [x,y,z]
v = zutil.rotate_vector(v,alpha,0.0)
return {'v1' : v[0], 'v2' : v[1], 'v3' : v[2]}
parameters = {
# units for dimensional quantities
'units' : 'SI',
# reference state
'reference' : 'IC_1',
'time marching' : {
'unsteady' : {
'total time' : 1.0,
'time step' : 1.0,
'order' : 'second',
},
'scheme' : {
'name' : 'lu-sgs',
'stage': 1,
#'name' : 'runge kutta',
#'stage': 5,
},
'lu-sgs' : {
'Number Of SGS Cycles' : 8,
'Min CFL' : 0.1,
'Max CFL' : 5.0,
'Include Backward Sweep' : True,
'Include Relaxation' : True,
'Jacobian Update Frequency' : 1,
'Jacobian Epsilon' : 1.0e-08,
'CFL growth' : 1.05,
'Use Rusanov Flux For Jacobian' : 'true',
'Finite Difference Jacobian' : 'false',
},
'multigrid' : 10,
'cfl': 2.5,
'cfl transport' : 2.5*0.5,
'ramp': { 'initial': 1.0, 'growth': 1.1 },
'cycles' : cycles,
},
'equations' : 'RANS',
'RANS' : {
'order' : 'euler_second',
'limiter' : 'vanalbada',
'precondition' : 'true',
'turbulence' : {
'model' : 'sst',
},
},
'material' : 'air',
'air' : {
'gamma' : 1.4,
'gas constant' : 287.0,
'Sutherlands const': 110.4,
'Prandtl No' : 0.72,
'Turbulent Prandtl No' : 0.9,
},
'IC_1' : {
'temperature':310.928,
'pressure':101325.0,
'alpha': alpha, # User defined variable used for post processing
'V': {
'vector' : zutil.vector_from_angle(alpha,0.0),
'Mach' : 0.85,
},
'Reynolds No' : 5.0e6,
'Reference Length' : 275.8,
'turbulence intensity':1.e-4,
'eddy viscosity ratio':0.1,
},
'BC_1' : {
'ref' : 7,
'type' : 'symmetry',
},
'BC_2' : {
'ref' : 3,
'type' : 'wall',
'kind' : 'noslip',
},
'BC_3' : {
'ref' : 9,
'type' : 'farfield',
'condition' : 'IC_1',
'kind' : 'riemann',
},
'write output' : {
'format' : 'vtk',
'surface variables': ['V','p','T','rho','walldist','yplus','mach','cp','eddy','pressureforce','frictionforce'],
'volume variables': ['V','p','T','rho','walldist','mach','cp','eddy'],
'frequency' : 500,
},
'report' : {
'frequency' : 10,
'forces' : {
'FR_1' : {
'name' : 'wall',
'zone' : [9,10,11,12,13],
'transform' : my_transform,
'reference area' : 594720.0*0.5, # half model area # half model area # half model area
},
},
},
}
"""
template = jinja2.Template(pyConf)
print template.render(alpha = argv[1], cycles = argv[2])
然后我修改了我的lambda函数,让这个模板,执行它,它将现在呈现的控制文件打印到stdio中,在lambda函数中,我已将stdio重定向到了我的exec函数,在那里我可以捕获它并将其流式传输到S3对象中,然后再将它们推回到S3。
import boto3
import jinja2
import sys
import StringIO
import contextlib
@contextlib.contextmanager
def stdoutIO(stdout=None):
old = sys.stdout
if stdout is None:
stdout = StringIO.StringIO()
sys.stdout = stdout
yield stdout
sys.stdout = old
s3 = boto3.resource('s3')
def main(json_input, context):
client = boto3.client('s3')
body = client.get_object(Bucket = "cfdworkflow2", Key='Control/control.py').get('Body').read()
c_body = convertBody(body)
s3.Object('cfdworkflow2', 'Control/parsedControl.py').put(Body=c_body)
def convertBody(body):
sys.argv = ['','3','100']
with stdoutIO() as s:
exec(body)
return s.getvalue()
发现重定向标准输入输出here
为了延长我会通过标准输入到lambda函数作为参数传递到神社模板的想法。
Jinja是一个模板库,它当然不仅限于HTML。但我不确定为什么你需要首先有一个模板,如果你只是从python文件中读取纯python字典。尽管对我来说,它看起来是一种处理confs的奇怪方式。你为什么不尝试使用YAML或JSON来创建一个conf文件,这样就很容易读取,操作和写回到S3。 [Here](http://docs.aws.amazon.com/lambda/latest/dg/with-s3.html)是一个使用AWS lambda从/到S3访问文件的教程。 – SRC
@SRC,运行的应用程序需要Python文件作为配置的格式,我会向OP中举例说明。我想我可以读取.py,将字典转换为JSON文件,处理该文件,然后将其转储回另一个python文件。至于写给S3的阅读,我已经有了这个工作。 – Lewiky
虽然这是一个糟糕的解决方案,但我强烈建议您检查一下代码/体系结构,这样您就不需要使用此解决方案,但是如果您有一个字符串(或包含少量行的文件)并且想要将其作为一个Python代码,然后你可以使用[eval](https://docs.python.org/3/library/functions.html#eval)或[exec](https://docs.python.org/3/library/ functions.html #exec) – SRC