0

yaml file:

$ cat ec2_attr.yml

treeroot:
    branch1:
        name: Node 1
        snap: |
          def foo():

              from boto3.session import Session
              import pprint

              session = Session(region_name='us-east-1')
              client = session.client('rds')

              resp = client.describe_db_cluster_snapshots(
                  SnapshotType='manual',
              )

              filtered = [x for x in resp['DBClusterSnapshots'] if x[
                  'DBClusterSnapshotIdentifier'].startswith('xxxxx')]
              latest = max(filtered, key=lambda x: x['SnapshotCreateTime'])
              print(latest['DBClusterSnapshotIdentifier'])

          foo()        
    branch2:
        name: Node 2

Code:

import yaml
import pprint

with open('./ec2_attr.yml') as fh:
    try:
        yaml_dict = yaml.load(fh)
    except Exception as e:
        print(e)
    else:
        exec("a = yaml_dict['treeroot']['branch1']['snap']")
        print('The Value is: %s' % (a))

Actual Output:

The Value is: def foo():

    from boto3.session import Session
    import pprint

    session = Session(region_name='us-east-1')
    client = session.client('rds')

    resp = client.describe_db_cluster_snapshots(
        SnapshotType='manual',
    )

    filtered = [x for x in resp['DBClusterSnapshots'] if x[
        'DBClusterSnapshotIdentifier'].startswith('xxxxx')]
    latest = max(filtered, key=lambda x: x['SnapshotCreateTime'])
    print(latest['DBClusterSnapshotIdentifier'])

foo()  

Expected output:

xxxxx-xxxx-14501111111-xxxxxcluster-2gwe6jrnev8a-2017-04-09

If I use exec as exec(yaml_dict['treeroot']['branch1']['snap']), Then it does print the value that I want, but I cannot capture that value into a variable. I understand that exec return value is None. However, I am trying to do something exactly similar to https://stackoverflow.com/a/23917810/1251660, and it is not working in my case.

Community
  • 1
  • 1
slayedbylucifer
  • 22,878
  • 16
  • 94
  • 123

1 Answers1

2

You can use exec like this:

import yaml
import pprint

with open('./a.yaml') as fh:
    try:
        yaml_dict = yaml.load(fh)
    except Exception as e:
        print(e)
    else:
      a = {}
      exec(yaml_dict['treeroot']['branch1']['snap'], {}, a)
      print('The Value is: %s' % (a['foo']()))

And change your YAML to this:

treeroot:
  branch1:
      name: Node 1
      snap: |
        def foo():
            return("test")

  branch2:
      name: Node 2

Actually, You can use exec(str, globals, locals)

The built-in functions globals() and locals() return the current global and local dictionary, respectively, which may be useful to pass around for use as the second and third argument to exec().

Also, You can read The exec Statement and A Python Mystery and locals and globals

RaminNietzsche
  • 2,683
  • 1
  • 20
  • 34