1

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

参考 -从 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

输入文件- 要对我的项目执行的操作列表。

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)

上面的代码可以很好地使用以下命令提要并生成文本属性文件。

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

生成输出文件

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

2 回答 2

1

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

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

如果您将StringIOs 替换为实际文件,则它应该相同。


注意:上面的代码假定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给变量时才有用。如果您不分配,则可以安全地忽略它们)。

于 2013-11-08T08:27:53.867 回答
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))
于 2013-11-08T12:24:46.523 回答