【问题标题】:Reading from text-file with namedtuple entries从带有命名元组条目的文本文件中读取
【发布时间】:2018-10-23 15:33:19
【问题描述】:

我有问题。我有一个由命名元组组成的列表。我将此列表写入 file.txt。现在我想读回来。我在这里发现建议使用 json 预先转换它而不是保存它。但我需要一个解决方案来解决我已经保存的文件。我的文本文件如下所示:

file.txt:

[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=1, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=2, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]

如果我使用拆分方法,它几乎是我想要的,但正如预期的字符串:

lines = input_data.split('\n')
lines
['[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]','[Hello(i=1,...),...],...]']

非常感谢你们!

【问题讨论】:

  • 请使用cmets对答案进行反馈;问题帖子就在那里。回答者不会收到对问题进行编辑的通知。

标签: python namedtuple


【解决方案1】:

您必须将文件解析为文本,并使用文本处理技术提取信息。

您可以在这里使用regular expression

import re

hello_pattern = re.compile(r'Hello\(i=(\d+), time=(\d+), x=(\d+), y=(\d+)\)')

此模式匹配您的 namedtuple 值的表示,并允许您访问每个值的数字,尽管是字符串:

>>> line = '[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]'
>>> hello_pattern.findall(sample)
[('0', '0', '0', '0'), ('0', '0', '0', '0')]

然后您可以再次将这些字符串转换为整数并重新创建实例;对于单行,列表理解将是:

[Hello(*map(int, match)) for match in hello_pattern.findall(line)]

以及在同一行上的演示:

>>> from collections import namedtuple
>>> Hello = namedtuple('Hello', 'i time x y')
>>> [Hello(*map(int, match)) for match in hello_pattern.findall(sample)]
[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]

所以完整的解决方案是:

import re
from collections import namedtuple

Hello = namedtuple('Hello', 'i time x y')  # or import your own ready definition
hello_pattern = re.compile(r'Hello\(i=(\d+), time=(\d+), x=(\d+), y=(\d+)\)')

data = []
with open('file.txt') as inputfile:
    for line in inputfile:
        recovered = [
            Hello(*map(int, match))
            for match in hello_pattern.findall(line)
        ]
        data.append(recovered)

【讨论】:

    【解决方案2】:

    尽管我讨厌宣传 eval(),但这一定是少数情况下任何替代解决方案都更糟糕的情况之一。

    line = "[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]"
    # Original definition, I assume
    Hello = namedtuple('Hello', ['i','time','x','y'])
    data = eval(line)
    #[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]
    

    注意在您读取的数据之前不是由您自己生成和保存的任何情况下,您都不应使用eval

    【讨论】:

    • 我不同意替代方案更糟。相当强烈。
    • @MartijnPieters 这取决于“更糟糕”的定义,这是基于意见的:)
    • 不,有客观标准:eval() 带来了在这种情况下不需要的安全风险,因为输入是完全规则的,因此可以使用专用工具进行解析。
    • @MartijnPieters 由于数据之前由 OP 保存,这正是eval 不会带来任何安全风险的上下文。
    • eval() 在没有进一步背景的情况下向新程序员教授时也存在未来安全风险。 始终包含完整的图片,并始终尝试寻找替代方案。除非有人完全理解 eval() 做什么和不做什么,否则应该避免。就像密码学和没有参数的 SQL。
    猜你喜欢
    • 2015-07-29
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多