【问题标题】:Python csv get original raw data linePython csv获取原始原始数据行
【发布时间】:2021-06-09 04:05:14
【问题描述】:

在 python 中,很容易读取和解析 csv 文件并逐行处理:

reader = csv.reader(open("my_csv_file.csv"))
for row in reader:
    # row is an array or dict 
    parsed_data = my_data_parser(row)
    

其中 my_data_parser 是我自己的一段逻辑,它接受输入数据、解析并执行逻辑。

如果我的解析器失败,我想记录 csv 文件的整个 original 行,但似乎从 csv 阅读器我无法再访问它。

是否可以检索原始原始线数据?

【问题讨论】:

    标签: python csv reader


    【解决方案1】:

    您可以使用

    访问行行号
    reader.line_num
    

    但似乎没有直接的方法可以访问实际线路(如doc)。这是避免在任何步骤将整个文件读取到内存的迭代方法:

    import csv 
    class MyException(Exception):
        pass
    
    def super_logic(line): # Some silly logic to get test code running
       if len(line) != 2 or line[1] != '1':
           raise MyException("Invalid value")
       print("Process: %s" % line)
    
    class LastLineReader:
        
        def __init__(self, fn ):
            self.fid = open(fn)
        def __iter__(self):
            return self
        def __next__(self):
            line = self.fid.readline() # Read single line and cache it local object
            if len(line) == 0:
                raise StopIteration()
            self.current_line = line.strip()
            return line
               
    
    reader_with_lines = LastLineReader( "my_csv_file.csv" )
    reader = csv.reader( reader_with_lines )
    for line in reader:
       try:
         super_logic(line)
       except MyException as e:
         print("Got exception: %s at line '%s'" % ( e, reader_with_lines.current_line ))
    

    (已编辑:删除其他解决方案,因为它们在其他 ppl 帖子中也可见)

    【讨论】:

    • 同意。如果您认为问题在于您的处理,那么只需打印行对象。如果您认为原始 CSV 行在文本文件中的格式不正确,那么您只需要关心行号。
    【解决方案2】:

    csv.reader() 似乎没有暴露它正在迭代的文件对象,但是,您可以使用 reader's line_num 属性来实现您想要的。

    例如:

    import csv
    
    file = open("my_csv_file.csv")
    
    lines = file.readlines()
    
    reader = csv.reader(lines)
    
    for row in reader:
        # row is an array or dict
        try:
            parsed_data = my_data_parser(row)
        except MyDataParserError:
            print(f"ERROR in line number {reader.line_num}")
            print("Full line:")
            print(lines[reader.line_num])
    
    file.close()
    

    另类

    如果您想避免总是将文件加载到内存中,您可以改为保留读取文件的初始方式,并且仅在发生错误时将整个文件读取到内存中:

    import csv
    
    reader = csv.reader(open("my_csv_file.csv"))
    for row in reader:
        # row is an array or dict 
        try:
            parsed_data = my_data_parser(row)
        except MyDataParserError:
            # Only read the whole file into memory when an error occurred.
            file = open("my_csv_file.csv")
            lines = file.readlines()
            file.close()
    
            print(f"ERROR in line number {reader.line_num}")
            print("Full line:")
            print(lines[reader.line_num])
    

    【讨论】:

    • 缺点是你不再使用 CSV 模块了。所以 row 是纯文本,您需要解析以逗号分隔,处理已由 CSV 处理的可选引号。另外,这种一次处理一行文本文件的方法将意味着任何多行单元格都将被处理得很糟糕。例如,一个 100 行的 CSV 文件可能是 250 行的文本文件。因为引用了换行符。
    • 我错过了部分解决方案 - 我现在已经更新了答案
    • 不错的解决方案!唯一的缺点是 file.readlines() 一次读取整个文件,对于大文件,它可能并不总是可取的。
    • 也意识到 - 添加了另一个解决方案。
    【解决方案3】:

    作为 reader.line_num 的替代品

    for index, row in enumerate(reader):
        print(i + 1, row)
    

    【讨论】:

      猜你喜欢
      • 2018-09-07
      • 1970-01-01
      • 2018-10-13
      • 2010-11-24
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-08
      • 2022-01-26
      相关资源
      最近更新 更多