Извлекайте отличные значения из yaml - PullRequest
0 голосов
/ 10 марта 2020

Мне нужно извлечь --my_dataset, --my_table и --s3_temp_path из файла ниже, используя скрипт python.

Мой файл:

▶ cat my_datasets/my_file.yml
__global__:
  role: myrole
  contact: sam@user.com

__default__:
  cc_policy: VERY_NEW
  act_num: 16384
  react_num: 16384
  with_start: 1
  where_to: my_file.log
  class: myClass
  my_arguements: >-
    -Dmy.num.1=4096
    -Dmy.num.2=true
    -Dmy.num.3=fgcd
  is_it: true
  if_not: false
  compure: dc1
  env: test
  my_compute: res-dc
  config: /my/file/config

first_adhoc:
  my_space: my_transfer
  doodle: my_transfer.tar.gz
  jar: my_transfer.jar
  my_dir: "dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10/dir11:my-deploy"
  my_arguments: >-
    m.big.class
    --sdrs
    --tz UTC
    --env test
    --my_dataset my_analytics
    --my_table onboarding_client_events
    --current_date 2020-09-22
    --my_project my_aws_project
    --s3_temp_path s3://test-wierd/
    --my_key_json dir1/dir2/dir3/dir4/keys.json
    --my_auth_file dir1/dir2/dir3/dir4/gcp/my_new.yml
    --my_proxy example.com:9999
    --write_mode write
    --update_option option1 option2

first_cron:
  my_space: my_transfer
  doodle: my_transfer.tar.gz
  jar: my_transfer.jar
  my_dir: "dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10/dir11:my-deploy"
  my_arguments: >-
    m.big.class
    --sdrs
    --tz UTC
    --env test
    --my_dataset my_analytics
    --my_table i_wish
    --current_date 2020-09-22
    --my_project my_aws_project
    --s3_temp_path s3://test-wierd/
    --my_key_json dir1/dir2/dir3/dir4/keys.json
    --my_auth_file dir1/dir2/dir3/dir4/gcp/my_new.yml
    --my_proxy example.com:9999
    --write_mode write
    --update_option option1 option2
  cron_schedule: "* * 4 * *"

У меня много файлы, подобные тому, который я упомянул выше в base_path, из всех файлов, которые мне нужны для получения --my_dataset, --my_table и --s3_temp_path.

Ниже показано, как долго я продвинулся. Мне удалось извлечь все файлы с помощью my_file.yaml рекурсивно, но я не могу извлечь вышеупомянутые отдельные значения.

Мой сценарий:

import fnmatch
import os
import re
import yaml


user_path = os.path.expanduser('~')
source_path = user_path + "/where/are/"
base_path = source_path + "/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10"


def find(pattern, base_path):
    results = []
    for root, dirs, files in os.walk(base_path):
        for name in files:
            if fnmatch.fnmatch(name, pattern):
                results.append(os.path.join(root, name))

    for result in results:
        stream = open(result, 'r')
        dictionary = yaml.load(stream)
        for key, value in dictionary.items():
            res = dict((k, dictionary[k]) for k in ['my_dataset', 'my_table', 's3_temp_path' ] 
                                        if k in dictionary) 
            print (key + " : " + str(value))

print find('my_file.yml', base_path)

Текущий результат:

▶ python myWork.py
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
None

Ожидаемые результаты:

{"my_dataset": "my_analytics", "my_table": "i_wish", "s3_temp_path": "s3://test-wierd/"}

Ответы [ 2 ]

0 голосов
/ 12 марта 2020

Спасибо за ответ, я смог решить эту проблему, написав следующий код.

import os
import yaml
tbl = []
def getNames(pattern, base_path):
    rsls = []
    for root, dirs, files in os.walk(base_path):
        for name in files:
            if fnmatch.fnmatch(name, pattern):
                rsls.append(os.path.join(root, name))
    for rsl in rsls:
        stream = open(rsl, 'r')
        dictionary = yaml.load(stream)
        for key, value in dictionary.items():
            if 'my_arguments' in value:
                arg_val = value['my_arguments']
                tname_fractions = []
                for col in col_names:
                    col_val = arg_val.split(col)[1].strip().split()[0]
                    tname_fractions.append(col_val)
                tbl_nm = ','.join(tname_fractions)
                tbls.append(tbl_nm)
                utl = list(set(tbls))

    return utl
0 голосов
/ 11 марта 2020

Ваш код создает впечатление, что вы просто написали несколько случайных строк, не задумываясь о структуре, по которой вы вообще пытаетесь ориентироваться.

Сначала давайте посмотрим, где находятся ваши значения: они содержатся в один длинный сложенный скаляр . Это будет загружено в строку в Python, вы не можете напрямую запрашивать значения через их имена, потому что YAML не понимает, что это параметры cmdline. Итак, давайте напишем функцию, которая извлекает значение из этой строки:

def get_cmdline_arg(name, cmdline):
  found = False
  for item in cmdline.split():
    if found: return item
    # if the current item is the searched name, the next item will be
    # its value
    found = (item == name)
  return "<not found>"

Теперь, имея это, давайте посмотрим, как получить строку my_arguments из структуры. Ваш YAML имеет четыре ключа на уровне root: __global__, __default__, first_adhoc и first_cron. Данные, которые вы ищете, находятся в first_adhoc и first_cron, поэтому давайте начнем с итерации этих двух значений (начиная с загруженного значения dictionary из вашего кода):

for k in ['first_adhoc', 'first_cron']:
  arguments = dictionary[k]['my_arguments']

Теперь у нас есть my_arguments значение, нам просто нужно получить значения аргумента:

  res = {}
  for name in ['my_dataset', 'my_table', 's3_temp_path']:
    res[name] = get_cmdline_arg('--' + name, arguments)
  print(k + ": " + str(res))
...