我想从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
答案 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_key
和nonlocal
非常有用当且仅当 分配变量。如果你没有分配给你可以安全地省略它们。)
答案 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))