我有一个包含以下内容的文本文件:
******** ENTRY 01 ********
ID: 01
Data1: 0.1834869385E-002
Data2: 10.9598489301
Data3: -0.1091356549E+001
Data4: 715
然后是一个空行,并重复更多类似的块,所有这些块都具有相同的数据字段。
我正在向Python移植一个C ++代码,某个部分逐行获取文件,检测文本标题,然后检测每个字段文本以提取数据。这看起来并不像一个智能代码,我认为Python必须有一些库来轻松地解析这样的数据。毕竟,它几乎看起来像一个CSV!
对此有何想法?
答案 0 :(得分:9)
实际上离CSV非常远。
您可以将该文件用作迭代器;以下生成器函数生成完整的部分:
def load_sections(filename):
with open(filename, 'r') as infile:
line = ''
while True:
while not line.startswith('****'):
line = next(infile) # raises StopIteration, ending the generator
continue # find next entry
entry = {}
for line in infile:
line = line.strip()
if not line: break
key, value = map(str.strip, line.split(':', 1))
entry[key] = value
yield entry
这会将文件视为迭代器,这意味着任何循环都会将文件前进到下一行。外环仅用于从一个部分移动到另一个部分;内部while
和for
循环完成所有实际工作;首先跳过行,直到找到****
标题部分(否则丢弃),然后遍历所有非空行以创建一个部分。
在循环中使用该功能:
for section in load_sections(filename):
print section
在文本文件中重复样本数据会导致:
>>> for section in load_sections('/tmp/test.txt'):
... print section
...
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
如果您愿意,可以添加一些数据转换器;密钥到可调用的映射可以:
converters = {'ID': int, 'Data1': float, 'Data2': float, 'Data3': float, 'Data4': int}
然后在生成器函数中,而不是entry[key] = value
执行entry[key] = converters.get(key, lambda v: v)(value)
。
答案 1 :(得分:4)
my_file:
******** ENTRY 01 ********
ID: 01
Data1: 0.1834869385E-002
Data2: 10.9598489301
Data3: -0.1091356549E+001
Data4: 715
ID: 02
Data1: 0.18348674325E-012
Data2: 10.9598489301
Data3: 0.0
Data4: 5748
ID: 03
Data1: 20.1834869385E-002
Data2: 10.954576354
Data3: 10.13476858762435E+001
Data4: 7456
Python脚本:
import re
with open('my_file', 'r') as f:
data = list()
group = dict()
for key, value in re.findall(r'(.*):\s*([\dE+-.]+)', f.read()):
if key in group:
data.append(group)
group = dict()
group[key] = value
data.append(group)
print data
印刷输出:
[
{
'Data4': '715',
'Data1': '0.1834869385E-002',
'ID': '01',
'Data3': '-0.1091356549E+001',
'Data2': '10.9598489301'
},
{
'Data4': '5748',
'Data1': '0.18348674325E-012',
'ID': '02',
'Data3': '0.0',
'Data2': '10.9598489301'
},
{
'Data4': '7456',
'Data1': '20.1834869385E-002',
'ID': '03',
'Data3': '10.13476858762435E+001',
'Data2': '10.954576354'
}
]
答案 2 :(得分:0)
一种非常简单的方法可能是
all_objects = []
with open("datafile") as f:
for L in f:
if L[:3] == "***":
# Line starts with asterisks, create a new object
all_objects.append({})
elif ":" in L:
# Line is a key/value field, update current object
k, v = map(str.strip, L.split(":", 1))
all_objects[-1][k] = v