【问题标题】:Edit parameters in a python file from another python file从另一个 python 文件编辑 python 文件中的参数
【发布时间】:2017-06-20 20:27:18
【问题描述】:

我有一个包含 dict 的 python 文件形式的应用程序配置文件,我正在运行一个 AWS lambda 函数来从 S3 获取这个 conf 文件,更改其中的三个变量,然后推送一个副本回到 S3。有什么简单的方法可以做到这一点?一位同事说要尝试 Jinja 模板,但这似乎仅限于 HTML 文件?

谢谢

python 配置文件的示例如下。我需要更改“alpha”和“cycles”变量

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
            },
        },
    },
}

【问题讨论】:

  • Jinja 是一个模板库,当然不仅限于 HTML。但是我不确定如果你读到的只是来自 python 文件的纯 python dict,为什么你首先需要一个模板。尽管在我看来,这是一种处理 confs 的奇怪方式。你为什么不尝试在 YAML 或 JSON 中创建一个 conf 文件,这样它会很容易读取、操作和写回 S3。 Here 是使用 AWS lambda 从 / 到 S3 访问文件的教程。
  • @SRC,运行的应用程序需要python文件作为config的格式,我会在OP中举个例子。我想我可以读取 .py,将 dict 转储到 JSON 文件中,对其进行处理,然后将其转储回另一个 python 文件。至于 S3 的阅读写作,我已经开始工作了。
  • 虽然,这是一个糟糕且糟糕的解决方案,我强烈建议您检查您的代码/架构,以便您不需要使用此解决方案,但如果您有一个字符串(或包含几行的文件) 并希望将其作为 python 代码执行,那么您可以使用 evalexec
  • @SRC 执行 conf 文件会达到什么效果?
  • 我不知道你还能如何做到这一点。但是在我看来this link 可能会有所帮助。最后一个答案。

标签: python amazon-web-services amazon-s3


【解决方案1】:

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)

【讨论】:

  • 感谢您的建议,并按照我发布的答案进行了扩展。
【解决方案2】:

我找到了一个解决方案,它并不漂亮,正如 SRC 所提到的,它是一个糟糕的解决方案,不应该在任何实际应用中使用,但它确实有效。

我听取了 milo 的建议,并将我的参考 control.py 文件转换为 Jinja 模板,如下所示:

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 函数中,我为我的 exec 函数重定向了 stdio,我可以在其中捕获它并流式传输它进入一个 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()

找到了重定向stdiohere的思路

为了扩展,我将通过标准输入传递给 lambda 函数作为 jinja 模板的参数。

【讨论】:

    猜你喜欢
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 2020-03-16
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多