拆分多个嵌套键,值并提取到文本文件

时间:2013-11-08 07:01:29

标签: python dictionary

我想从dict中拆分嵌套键和值并写入文本文件。我尝试了以下代码来提取嵌套的键和值。但是密钥的值会被最新的迭代结果覆盖。提取结果将用于selenium输入参数。

参考 - Split dictionary key and list of values from dict

请让我知道我的结果。

预期的TXT文件

step0.username=test@url.net
step0.url=http://demo.url.net 
step0.password=mytester
step0.create-folder-name=demo
step1.url=http://demo.url.net 
step1.username=test123@url.net 
step1.password=mytester123
step1.select-folder-name=demo124
step1.share-folder-name=demo124

INPUT FILE - 要对我的项目执行的操作列表。

login url=http://demo.url.net username=test@url.net password=mytester
create-folder create-folder-name=demo
logout
login url=http://demo.url.net username=test123@url.net 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)

以上代码可以正常使用以下命令Feed并生成文本属性文件。

login url=http://demo.url.net username=test@url.net password=mytester
create-folder create-folder-name=demo select-folder select-folder-name=demo logout

生成OUTPUT文件

username=test123@url.net
select-folder-name=demo124
share-folder-name=demo124
create-folder-name=demo
url=http://demo.url.net
password=mytester123

2 个答案:

答案 0 :(得分:1)

您目前拥有的解决方案无法工作,因为使用dict您将失去有关步骤顺序的信息。但是我相信有一个更简单的解决方案:

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 username=test@url.net password=mytester
   ...: create-folder create-folder-name=demo
   ...: logout
   ...: login url=http://demo.url.net username=test123@url.net 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
step0.username=test@url.net
step0.password=mytester
step0.create-folder-name=demo
step1.url=http://demo.url.net
step1.username=test123@url.net
step1.password=mytester123
step1.select-folder-name=demo124
step1.share-folder-name=demo124

如果用实际文件替换StringIO,它应该是相同的。


注意:上面的代码假设是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__的{​​{1}}方法的调用。

(我提醒current_keynonlocal非常有用当且仅当 分配变量。如果你没有分配给你可以安全地省略它们。)

答案 1 :(得分: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))