杰瑞科技汇

如何跳过Python的parseerror错误?

这些错误通常由相应的解析库抛出,

如何跳过Python的parseerror错误?-图1
(图片来源网络,侵删)
  • JSON: json.JSONDecodeError
  • XML: xml.etree.ElementTree.ParseError
  • CSV: csv.Error
  • HTML (BeautifulSoup): bs4.FeatureNotFound 或其他解析器相关的错误。

要“跳过”这些错误,核心思想就是使用 try...except 结构来捕获异常,然后让程序继续执行,而不是崩溃。

下面我将分步讲解,并提供不同场景下的代码示例。


核心方法:try...except 结构

这是处理所有 Python 异常的标准方法。

try:
    # 尝试执行可能会出错的代码
    result = parse_some_data(data)
    # 如果成功,处理 result
    print(f"解析成功: {result}")
except SpecificParseError as e:
    # 如果发生了 SpecificParseError 类型的错误,执行这里的代码
    print(f"解析失败,已跳过,错误信息: {e}")
    # 程序会继续从这里往下执行,而不会崩溃
# 无论是否发生错误,这里的代码都会被执行
print("继续处理下一个数据项...")

跳过单个 JSON 解析错误

假设你有一个字符串列表,其中大部分是有效的 JSON,但有一个是无效的,你只想处理有效的,并跳过无效的那个。

如何跳过Python的parseerror错误?-图2
(图片来源网络,侵删)

错误类型: json.JSONDecodeError

代码示例:

import json
data_strings = [
    '{"name": "Alice", "age": 30}',
    '{"name": "Bob", "age": 25}',
    '{"name": "Charlie", "age": 40,}',  # 最后多了一个逗号,是无效的 JSON
    '{"name": "David", "age": 35}'
]
valid_data = []
for s in data_strings:
    try:
        # 尝试解析 JSON 字符串
        person_data = json.loads(s)
        valid_data.append(person_data)
        print(f"成功解析: {person_data['name']}")
    except json.JSONDecodeError as e:
        # 捕获 JSON 解析错误
        print(f"!!! 跳过无效的 JSON: {s}")
        print(f"    错误原因: {e}")
        # 使用 pass 语句表示什么都不做,直接继续循环
        pass
print("\n最终收集到的有效数据:")
for item in valid_data:
    print(item)

输出:

成功解析: Alice
成功解析: Bob
!!! 跳过无效的 JSON: {"name": "Charlie", "age": 40,}
    错误原因: Expecting property name enclosed in double quotes: line 1 column 33 (char 32)
成功解析: David
最终收集到的有效数据:
{'name': 'Alice', 'age': 30}
{'name': 'Bob', 'age': 25}
{'name': 'David', 'age': 35}

处理文件中的多行数据,跳过解析失败的行

这是一个非常常见的用例,比如处理一个 CSV 或每行都是 JSON 的日志文件。

如何跳过Python的parseerror错误?-图3
(图片来源网络,侵删)

代码示例:

假设我们有一个 data.jsonl 文件,内容如下:

{"id": 1, "user": "user1"}
{"id": 2, "user": "user2"}
{"id": 3, "user": "user3",}  # 无效行
{"id": 4, "user": "user4"}

Python 代码:

import json
valid_entries = []
file_path = 'data.jsonl'
try:
    with open(file_path, 'r', encoding='utf-8') as f:
        for line_number, line in enumerate(f, 1):
            line = line.strip()  # 去掉首尾的空白字符
            if not line:  # 跳过空行
                continue
            try:
                entry = json.loads(line)
                valid_entries.append(entry)
                print(f"成功解析第 {line_number} 行: {entry}")
            except json.JSONDecodeError as e:
                print(f"!!! 第 {line_number} 行解析失败,已跳过,内容: '{line}'")
                print(f"    错误原因: {e}")
                pass  # 跳过此行,继续处理下一行
except FileNotFoundError:
    print(f"错误: 文件 {file_path} 未找到。")
print("\n成功解析的总条目数:", len(valid_entries))

输出:

成功解析第 1 行: {'id': 1, 'user': 'user1'}
成功解析第 2 行: {'id': 2, 'user': 'user2'}
!!! 第 3 行解析失败,已跳过,内容: '{"id": 3, "user": "user3",}'
    错误原因: Expecting property name enclosed in double quotes: line 1 column 27 (char 26)
成功解析第 4 行: {'id': 4, 'user': 'user4'}
成功解析的总条目数: 3

使用 csv 模块跳过格式错误的行

对于 CSV 文件,错误类型通常是 csv.Error

代码示例:

假设有一个 bad_data.csv 文件:

Name,Age,City
Alice,30,New York
Bob,25  # 缺少一个字段
Charlie,40,Los Angeles

Python 代码:

import csv
valid_rows = []
file_path = 'bad_data.csv'
try:
    with open(file_path, 'r', encoding='utf-8') as f:
        # csv.reader 会自动处理引号等,但如果行列数不匹配会报错
        reader = csv.reader(f)
        header = next(reader)  # 读取表头
        print(f"表头: {header}")
        for row_number, row in enumerate(reader, 2): # 从第2行开始计数
            try:
                # 这里可以添加更复杂的验证逻辑
                # 检查行是否包含预期的列数
                if len(row) != len(header):
                    raise ValueError(f"列数不匹配: 期望 {len(header)} 列,实际 {len(row)} 列")
                valid_rows.append(dict(zip(header, row)))
                print(f"成功解析第 {row_number} 行: {row}")
            except (csv.Error, ValueError) as e:
                # 同时捕获 csv.Error 和我们自定义的 ValueError
                print(f"!!! 第 {row_number} 行解析失败,已跳过,内容: {row}")
                print(f"    错误原因: {e}")
                pass
except FileNotFoundError:
    print(f"错误: 文件 {file_path} 未找到。")
print("\n成功解析的总行数:", len(valid_rows))

输出:

表头: ['Name', 'Age', 'City']
成功解析第 2 行: ['Alice', '30', 'New York']
!!! 第 3 行解析失败,已跳过,内容: ['Bob', '25']
    错误原因: 列数不匹配: 期望 3 列,实际 2 列
成功解析第 4 行: ['Charlie', '40', 'Los Angeles']
成功解析的总行数: 2

总结与最佳实践

  1. 明确异常类型:首先确定你使用的库在解析失败时会抛出什么具体的异常类(如 json.JSONDecodeError),使用 except 时捕获这个具体的异常,而不是笼统的 except Exception:,这样可以更精确地处理问题。

  2. 记录错误信息:在 except 块中,至少应该打印出错误信息 (e) 和导致错误的数据(失败的行号或行内容),这对于后续调试和数据清洗至关重要。

  3. pass 的使用:当你的目的仅仅是“跳过”时,pass 语句是最简单直接的选择,它表示“什么都不做,继续执行”。

  4. 处理文件时使用 with 语句:这能确保文件在操作完成后(无论是否发生错误)都会被正确关闭,是 Python 的推荐做法。

  5. 考虑更复杂的逻辑:在某些情况下,你可能不想简单地跳过,你可以:

    • 将错误的数据记录到一个单独的“错误日志”文件中。
    • 尝试修复数据(用默认值填充缺失的字段)。
    • 统计错误发生的频率,如果错误过多,可能需要检查数据源或解析逻辑。

通过掌握 try...except 结构,你就可以稳健地处理各种数据解析任务,让你的程序更加健壮。

分享:
扫描分享到社交APP
上一篇
下一篇