【问题标题】:What is a better way to readlines from Python file?从 Python 文件中读取行的更好方法是什么?
【发布时间】:2026-02-26 11:15:01
【问题描述】:

这是我的python文件:-

TestCases-2
Input-5
Output-1,1,2,3,5
Input-7
Ouput-1,1,2,3,5,8,13

我想要的是这个:-

  • 变量test_no = 2(测试用例数)
  • 列表testCaseInput = [5,7]
  • 列表testCaseOutput = [[1,1,2,3,5],[1,1,2,3,5,8,13]]

我尝试过这样做:

               testInput = testCase.readline(-10)

        for i in range(0,int(testInput)):
            testCaseInput = testCase.readline(-6)
            testCaseOutput = testCase.readline(-7)

下一步是在(',') 的基础上去除数字,然后将它们放入一个列表中。

奇怪的是,readline(-6) 没有给出预期的结果。

有没有更好的方法来做到这一点,显然我错过了。

我不介意在这里使用序列化,但我想让某人像我展示的那样编写一个文本文件然后从中取出数据变得非常简单。该怎么做?

【问题讨论】:

  • 您期待什么结果,您认为 .readline() 方法的负参数到底应该做什么?
  • 我期望 readline(-6) 它做的,或者它正在做的是跳到行的第 6 个字符,然后从那里存储到行尾'\n' 结尾。

标签: python parsing multiline


【解决方案1】:

readline 方法的否定参数指定要读取的字节数。我不认为这是你想要做的。

相反,使用 readlines() 将所有内容一次全部拉入列表更简单:

with open('data.txt') as f:
    full_lines = f.readlines()

# parse full lines to get the text to right of "-"
lines = [line.partition('-')[2].rstrip() for line in full_lines]

numcases = int(lines[0])
for i in range(1, len(lines), 2):
    caseinput = lines[i]
    caseoutput = lines[i+1]
    ...

这里的想法是分离关注点(数据的来源、'-' 的解析以及如何处理案例的业务逻辑)。这比在每一步都有一个 readline() 和冗余的解析逻辑要好。

【讨论】:

  • readlines() 保留换行符。我倾向于使用 f.read().splitlines() 代替小输入文件。
  • Corey,那也可以。我倾向于在单独的行上使用 rstrip()。
【解决方案2】:

我不确定我是否完全按照你想要做的,但我想我会尝试这样的事情:

testCaseIn = [];
testCaseOut = [];

for line in testInput:
    if (line.startsWith("Input")):
        testCaseIn.append(giveMeAList(line.split("-")[1]));
    elif (line.startsWith("Output")):
        testCaseOut.append(giveMeAList(line.split("-")[1]));

其中giveMeAList() 是一个函数,它采用逗号分隔的数字列表,并从中生成列表数据。

我没有测试过这段代码,但是当我过去想制作配置文件时,我写过一些使用这种结构的东西。

【讨论】:

  • 当然,这正是我以更好的方式编写的内容。谢谢你。 Pickle 会让我的工作更轻松吗?
  • 我没用过。 Pickle 总是让我印象深刻,因为它可以将 python 对象转换为文件,然后再将它们转换回对象,而不是让用户编写配置内容,然后将其转换为对象。如果您正在制作生产代码,您可能需要更健壮的东西,但如果您只是一起破解一些东西,我认为像这样的简单配置系统就足够了。如果你想更冗长,你可以把一些东西和 XML 放在一起。
  • 我喜欢这个变体的简单性。
  • @Oliver 非常有用的建议。谢谢。
【解决方案3】:

您可以为此使用正则表达式,这样会更容易。见问题:python: multiline regular expression

对于你的情况,试试这个:

import re
s = open("input.txt","r").read()
(inputs,outputs) = zip(*re.findall(r"Input-(?P<input>.*)\nOutput-(?P<output>.*)\n",s))

然后根据需要split(",")每个输出元素

如果你这样做,你会得到好处,你不需要输入文件的第一行,所以你不需要提前指定你有多少条目。

您还可以从上面的代码中取出解压缩(即zip(*...)),然后您可以一次处理每个输入和输出一对。我的猜测是这实际上正是你想要做的。

编辑想给你一个完整的例子来说明我刚才的意思。我假设这是一个测试脚本,所以我会说使用模式匹配迭代器的力量来帮助你的代码更短更简单:

for (input,output) in re.findall(r"Input-(?P<input>.*)\nOutput-(?P<output>.*)\n",s):
  expectedResults = output.split(",")

  testResults = runTest(input)
  // compare testResults and expectedResults ...

【讨论】:

  • 如果您对正则表达式感到满意,这是一种非常简洁的方法。它很好地表达了业务逻辑。它还可以很好地将读取与解析与处理结果分开。这使代码更易于维护(如果您对正则表达式感到满意)。
  • 感谢积极的 cmets。为什么这种方法应该依赖于对正则表达式的熟悉程度?如果您对它们感到不舒服,这是对它们力量的相对温和的介绍。
【解决方案4】:
  1. 这行有错误:

    Ouput-1,1,2,3,5,8,13  // it should be 'Output' not 'Ouput
    
  2. 这应该可行:

    testCase = open('in.txt', 'r')
    testInput = int(testCase.readline().replace("TestCases-",""))
    for i in range(0,int(testInput)):
        testCaseInput = testCase.readline().replace("Input-","")
        testCaseOutput = testCase.readline().replace("Output-","").split(",")
    

【讨论】:

  • 这将存储测试用例或任意数量的测试用例。谢谢你。但是,泡菜会让我的工作更轻松吗?
  • @Hiccup 如果您正在读取的文件是您的 python 程序的输出,那么是的,pickle.dump() 和 pickle.load() 会更容易。