You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免CSV文件重复写入相同数据?技术实现求助

解决CSV重复写入的几种实用方案

面对这种定时运行、不能重复写入的需求,我给你两个最常用的解决思路,看哪种更适配你的场景:

方案一:数据库标记法(最推荐)

既然你的数据来自数据库,而且查询条件是check=0,那最根本的办法就是写入CSV后,把这些已处理的记录标记为已完成,这样下次查询就不会再拿到它们了。

修改后的代码大概是这样:

import csv
import psycopg2  # 假设你用的是PostgreSQL,其他数据库逻辑类似

# 初始化数据库连接
conn = psycopg2.connect(host="your_host", dbname="your_db", user="your_user", password="your_pwd")
try:
    conn.autocommit = False  # 开启事务,保证写入和标记操作的原子性
    read_cursor = conn.cursor()
    # 查询所有未处理的记录
    read_cursor.execute("select item, check from items where check=0")
    records = list(read_cursor)  # 先把查询结果存到内存,方便后续处理

    if records:
        # 写入CSV:如果要保留所有历史记录用"a"追加,若只存最新批次用"w"覆盖
        with open('quantity_checker.csv', "a", newline="") as f:
            writer = csv.writer(f, delimiter=';')
            # 判断文件是否为空,为空则先写表头
            import os
            if os.stat('quantity_checker.csv').st_size == 0:
                writer.writerow(['item', 'check'])
            writer.writerows(records)
        
        # 批量标记这些记录为已处理(比如把check设为1)
        item_list = [record[0] for record in records]
        update_cursor = conn.cursor()
        update_cursor.execute(
            "update items set check=1 where item = any(%s)",
            (item_list,)
        )
    conn.commit()  # 事务提交
except Exception as e:
    conn.rollback()  # 出错则回滚所有操作
    print(f"处理失败:{str(e)}")
finally:
    conn.close()  # 关闭数据库连接

为什么首推这个方案?因为数据库是数据的唯一可信来源,用它标记处理状态最可靠,不会因为CSV文件损坏、丢失导致重复判断出错。而且事务机制能保证:要么CSV写入成功且数据库标记完成,要么全部回滚,避免数据不一致的情况。

方案二:本地CSV校验法(适合不能修改数据库的场景)

如果因为权限或业务限制,没法修改数据库的check字段,那只能通过本地读取已有的CSV,对比后过滤掉重复记录再写入。

思路是:先提取CSV里已有的item(或item+check组合,根据你的业务唯一性规则),再从数据库查询结果中过滤掉已存在的记录,最后写入CSV。

代码示例:

import csv
import os

csv_path = 'quantity_checker.csv'
# 读取已有CSV,收集已存在的item
existing_items = set()
if os.path.exists(csv_path):
    with open(csv_path, "r", newline="") as f:
        reader = csv.reader(f, delimiter=';')
        next(reader)  # 跳过表头
        for row in reader:
            if row:  # 避免空行干扰
                existing_items.add(row[0])

# 查询数据库未处理记录
conn = ...  # 你的数据库连接代码
read_cursor = conn.cursor()
read_cursor.execute("select item, check from items where check=0")
# 过滤掉已存在的记录
new_records = [row for row in read_cursor if row[0] not in existing_items]

# 写入新记录到CSV
if new_records:
    with open(csv_path, "a", newline="") as f:
        writer = csv.writer(f, delimiter=';')
        # 文件为空时先写表头
        if not os.path.exists(csv_path) or os.stat(csv_path).st_size == 0:
            writer.writerow(['item', 'check'])
        writer.writerows(new_records)

这个方案的缺点是:如果CSV被手动修改、删除,就会导致重复写入;而且如果多进程同时运行,可能出现竞争问题(不过你是每小时运行一次,大概率不会有这个问题)。

额外注意点

  • 如果item不是唯一标识(比如同一个item可能多次出现check=0的情况),那就要用item+check组合,或者数据库主键来判断重复。
  • 定时运行建议用系统定时任务(比如Linux的cron、Windows的任务计划),不要让代码一直循环sleep,这样更稳定可靠。

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:40:58