2013-11-08 2 views
1

Я хотел бы разделить вложенный ключ и значение из dict и записать в текстовый файл. Я попытался использовать следующий код для извлечения вложенных ключей и значений. Но значения ключа перезаписываются последним результатом итерации. Извлеченный результат будет использоваться для входного параметра селена.Сплит множественный вложенный ключ, значения и извлечение в текстовый файл

Ссылка - Split dictionary key and list of values from dict

Пожалуйста, дайте мне знать, чтобы получить мой результат.

ОЖИДАЕМЫЕ TXT ФАЙЛ

[email protected] 
step0.url=http://demo.url.net 
step0.password=mytester 
step0.create-folder-name=demo 
step1.url=http://demo.url.net 
[email protected] 
step1.password=mytester123 
step1.select-folder-name=demo124 
step1.share-folder-name=demo124 

входной файл - список действий, которые будут выполняться на моем проекте.

login url=http://demo.url.net [email protected] password=mytester 
create-folder create-folder-name=demo 
logout 
login url=http://demo.url.net [email protected] password=mytester123 
select-folder select-folder-name=demo124 
share-folder share-folder-name=demo124 
logout 

Следующий код обрабатывает входной файл.

def read_file(file_path): 
    result = defaultdict(dict) 
    item = count() 
    with open(file_path) as f: 
     for line in f: 
      if not line: 
       continue 
      parts = line.split() 
      result[next(item)][parts[0]] = dict(p.split('=') for p in parts[1:]) 
    return dict(result) 

Для разбивки вложенного ключа и значения и сохранения в текстовый файл следующее.

def generate_properties_file(filepath,dict_in): 
    try: 
     print "File PATH" , filepath 
     print "Generating user property file - %s" %(filepath) 
     with open(filepath,'wb') as f: 
      for key,value in dict_in.iteritems(): 
       output_result ='\n'+str(key)+'='+str(value) 
       f.write(output_result) 
    except IOError: 
     print "Unable to write the file :%s " %(filepath) 

def extract_value(dict_in,dict_out): 
    for key,value in dict_in.iteritems(): 
     if isinstance(value,dict):  #if value as a dictionary 
      extract_value(value,dict_out) 
     elif isinstance(value,list): # if value in a list 
      for i in value: 
       extract_value(i,dict_out) 
     else: 
      dict_out[key] = value 
    return dict(dict_out) 

def get_property(file_path): 
    lib_dict = {} 
    results = read_file(file) 
    myextracted_data = extract_value(results,lib_dict) 
    generate_properties_file(os.path.abspath('catalog/user.properties'),myextracted_data) 

if __name__=='__main__': 

    file = os.path.abspath('catalog/commands.txt') 
    get_property(file) 

Над кодом работает отлично со следующей подачей команды и созданием файла свойств текста.

login url=http://demo.url.net [email protected] password=mytester 
create-folder create-folder-name=demo select-folder select-folder-name=demo logout 

Сгенерированный выходной файл

[email protected] 
select-folder-name=demo124 
share-folder-name=demo124 
create-folder-name=demo 
url=http://demo.url.net 
password=mytester123 
+0

Можете ли вы показать нам, как вы называете эту функцию и какой выход вы получить? Я не понимаю, почему вы используете функцию «extract_value», поэтому укажите пример использования, чтобы выяснить, что именно вы хотите сделать. – Bakuriu

+0

Я обновил вопрос. – raj

ответ

1

решение, которое вы в настоящее время не может работы, потому что с помощью dict s вы теряете информацию о порядке шагов. Однако я считаю, что это гораздо проще решение: использование

from itertools import count, groupby 

def make_login_key(): 
    counter = count() 
    current_key = None 
    def key(line): 
     nonlocal current_key 
     if line.startswith('login'): 
      # we found the start of a new step, so change key 
      current_key = next(counter) 
     return current_key 
    return key 

def find_steps(fobj): 
    for _, group in groupby(fobj, key=make_login_key()): 
     step = [] 
     for line in group: 
      step.extend(line.split()[1:]) 
     yield step 



def format_steps(steps, fobj): 
    for i, step in enumerate(steps): 
     for part in step: 
      fobj.write('step{}.{}={}\n'.format(i, *part.split('='))) 

Пример:

In [2]: from io import StringIO 

In [3]: input_file = StringIO('''login url=http://demo.url.net [email protected] password=mytester 
    ...: create-folder create-folder-name=demo 
    ...: logout 
    ...: login url=http://demo.url.net [email protected] password=mytester123 
    ...: select-folder select-folder-name=demo124 
    ...: share-folder share-folder-name=demo124 
    ...: logout''') 

In [4]: output_file = StringIO() 

In [5]: format_steps(find_steps(input_file), output_file) 

In [6]: print(output_file.getvalue()) 
step0.url=http://demo.url.net 
[email protected] 
step0.password=mytester 
step0.create-folder-name=demo 
step1.url=http://demo.url.net 
[email protected] 
step1.password=mytester123 
step1.select-folder-name=demo124 
step1.share-folder-name=demo124 

Если заменить StringIO S с фактическим файлом он должен то же самое.


Примечание: Приведенный выше код предполагает python3 (в частности nonlocal заявление). Это довольно легко обойти. Простой способ заключается в использовании list:

def make_login_key(): 
    counter = count() 
    current_key = [None] 
    def key(line): 
     if line.startswith('login'): 
      current_key[0] = next(counter) 
     return current_key[0] 
    return key 

Это работает, так как current_key[0] = next(counter) делает не назначить counter_key. Это вызов метода __setitem__current_key.

(напоминаю, что nonlocal и global полезны тогда и только тогда, когда выназначить к переменным. Если вы не назначаете вы можете смело опустить их).

+0

Это более полезно для моего проекта. – raj

+0

Похоже, что ключевое слово nonlocal работает с python 3.x и не в python 2.7 – raj

+0

@raj Да. Это легко обойти. Например, вы можете использовать 'current_key = [None]' и вместо выполнения 'current_key = next (counter)' do 'current_key [0] = next (counter)'. Обратите внимание, что вам не нужно использовать 'nonlocal counter', поскольку вы никогда не назначаете его (теперь я обновлю свой ответ). – Bakuriu

1

Похоже, вы немного сбиваете с толку.Как насчет

import re 

def parse(fp): 
    c = -1 
    for line in fp: 
     if line.startswith('login'): 
      c += 1 
     for k, v in re.findall(r'(\S+?)=(\S+)', line): 
      yield 'step{}.{}={}\n'.format(c, k, v) 

, а затем

with open(INPUT) as fin, open(OUTPUT, 'w') as fout: 
    fout.writelines(parse(fin)) 
Смежные вопросы