【问题标题】:Python - reading data from one file and selectively writing to a new filePython - 从一个文件中读取数据并有选择地写入一个新文件
【发布时间】:2014-12-05 22:08:38
【问题描述】:

提前感谢您的帮助。

我是 Python 新手,正在尝试将文件从一种格式转换为另一种格式。

这是我的代码:

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        if line and line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            fnew.write(data[0])
        if not line:  break

print('end of program')
fs.close
fnew.close

文件的基本格式在顶部包含注释的标题,然后是数据行。

我遇到的问题是我的 fnew.write(data[0]) 行。我收到以下错误:

IndexError: 列表索引超出范围

行拆分拆分了八列数据,我想删除其中的前两列。所以,最终,我想要做的是重写整个文件减去前两列。我需要做一些更复杂的重新格式化,但我希望如果我能理解这一步中的错误,我可能会弄清楚如何做剩下的。

------------- 更新

阿巴内特,你是对的。这是导致错误的换行符。但是,正如您所说,在尝试添加支票时我遇到了另一个问题。当我执行下面的代码时,一切都冻结了我。如果我删除“如果数据:”检查,那么它会运行但给我同样的“索引超出范围”错误。

我还尝试在删除“if data:”检查的情况下运行它,并使用不包含换行符的示例数据文件,它也冻结了我。

谁能解释这可能是什么原因造成的?

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        for line in f:
            if line[0]=='#':
                print(line)
                fnew.write(line + '\n')
            else:
                data=line.split()
                if data:
                    print(data[0])
                    fnew.write(data[0] + '\n')

print('end of program')
fs.close
fnew.close

------------- 更新 2

以下代码有效。感谢 abarnet 澄清无限循环问题。我遇到的最后一个问题是数据的第一行,无论是换行符还是标题行都被忽略并且不会在输出中打印。

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    line = f.readline()
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')
fnew.close()

【问题讨论】:

  • 尝试将错误的 fwrite 包装在 try-except 块中,并在 except 块中打印数据以查看您有什么
  • 在您尝试写入之前调用您的数据变量的 print。它输出什么?
  • 顺便说一句..您可以将这三行“with fs as f: / while True: / line = f.readline()”替换为以下“for line in fs.readlines() :"。这不会解决你的问题,但它会让你的代码看起来更好(我的意思是更简单)。

标签: python writing


【解决方案1】:

首先,如果line 为空会怎样?

您最终会到达if not line: break。但在你到达那里之前,你会到达第一个else:(因为line and line[0]=='#' 不是真的)。所以,你的data = line.split() 会给你data = []。然后data[0] 将引发IndexError

只需先移动if not line: break 测试:

while True:
    line = f.readline()
    if not line:
        break
    elif line[0]=='#':
        print(line)
        fnew.write(line + '\n')
    else:
        data=line.split()
        fnew.write(data[0])

话虽如此,首先有一个更简单的方法来编写它。循环遍历文件将为您提供每一行,就像 while 围绕 readline 循环一样,除了当它到达 EOF 时,循环会自动结束,您无需测试任何内容或 break

for line in f:
    if line[0]=='#':
        print(line)
        fnew.write(line + '\n')
    else:
        data=line.split()
        fnew.write(data[0])

但是如果行不是为空,如果它只是空白,或纯空格会发生什么?例如,当您在' \n' 上调用split() 时会发生什么?同样,您会得到一个空列表。因此,如果可能的话,您将再次遇到同样的问题——当然,在这种情况下您可能不想break。我不确定您想做什么,但假设您只想跳过空白链接。因此,只需将 else 块替换为:

data=line.split()
if data:
    fnew.write(data[0])

作为旁注,在第一种情况下使用fnew.write(line + '\n') 非常奇怪,因为该行已经以\n 结束,所以你只是添加了一个额外的换行符,但在另一种情况下使用fnew.write(data[0]) ,其中data[0] 不以换行符结尾,因此您只需将一系列第一列合并为一个大词,并在末尾添加下一条评论……


您的新代码的问题在于,您没有替换readline() 周围的while True: 循环与for line in f: 循环,而是两者 .

所以,第一次通过while 循环,它读取第一行,然后读取文件中的每一行,然后完成。然后,第二次通过while 循环,它读取最后剩下的任何内容,然后读取所有剩余的 0 行,然后完成。它会一直持续下去,一遍又一遍地读取最后的 0 行,直到时间结束,因为您永远不会将 break 排除在 while True: 之外。

更新后的代码中还有一些其他问题。

  • fs.close 只是引用该方法,而没有实际调用它。调用时需要括号,例如 fs.close()
  • 但无论如何你都不想要fs.close()with 语句的全部意义在于它会自动关闭文件。
  • 您可能还想对fnew 使用with 语句。

所以:

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')

【讨论】:

  • 感谢您的帮助。我用您推荐的更改更新了上面的代码。出于某种原因,当我尝试执行它时,代码冻结在我身上。
  • @DataCruncher:查看我的更新答案以解释您做错了什么以及如何解决它。
  • 感谢您澄清无限循环以及文件关闭。我更新了顶部的代码。它按预期工作,但是由于某种原因它没有打印文件的第一行。
  • @DataCruncher:它没有打印文件的第一行,因为你在顶部写了line = f.readline(),它读取第一行,然后不对该值做任何事情。在我的代码中没有调用readline;你为什么加一个?更一般地说,您实际上是在尝试了解它的作用,还是只是在寻找可以复制和粘贴而无需考虑的魔术代码?后者你不会走得太远。
猜你喜欢
  • 2021-01-23
  • 2018-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-26
相关资源
最近更新 更多