数据存储为什么只能保存最后一条

想问问各位
为什么我用线程池来下载数据保存的excel中,只能保存最后一条数据
用的是openpyxl储存的
各位有头绪吗

当你使用线程池下载数据时,线程池中的线程可能会同时向同一个Excel文件写入数据,这可能会导致写入数据的冲突,从而只保存最后一条数据。


```python
import openpyxl
from concurrent.futures import ThreadPoolExecutor

def write_data_to_excel(excel_path, row, col, data):
    try:
        wb = openpyxl.load_workbook(excel_path)
    except FileNotFoundError:
        wb = openpyxl.Workbook()

    ws = wb.active
    ws.cell(row=row, column=col, value=data)

    with open(excel_path, 'a') as f:
        wb.save(f)

def download_and_save_data(url, excel_path, row, col):
    # 下载数据
    data = download_data(url)

    # 保存数据到Excel
    write_data_to_excel(excel_path, row, col, data)

def main():
    excel_path = 'data.xlsx'
    urls = [...]
    row = 1
    col = 1

    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = []
        for url in urls:
            futures.append(executor.submit(download_and_save_data, url, excel_path, row, col))
            row += 1
            col += 1

        # 等待所有任务完成
        for future in futures:
            future.result()

if __name__ == '__main__':
    main()




```

在这个示例中,我们定义了一个write_data_to_excel函数,它使用openpyxl库将数据写入Excel文件。为了避免冲突,我们使用了一个with open(excel_path, 'a') as f:的语句来打开Excel文件,这样每个线程都可以在文件末尾追加数据。注意,这里我们需要传递文件对象而不是文件名给wb.save(),否则可能会导致冲突。

在download_and_save_data函数中,我们首先下载数据,然后调用write_data_to_excel函数将数据写入Excel文件。

在main函数中,我们使用ThreadPoolExecutor创建了一个线程池,并将download_and_save_data函数提交给线程池来执行。注意,我们将每个任务的行和列位置分别保存在row和col变量中,以确保写入的数据不会发生冲突。

最后,在等待所有任务完成后,我们的Excel文件中应该包含了所有下载的数据。

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7475419
  • 这篇博客你也可以参考下:python openpyxl 向已存在的excel表格中写入数据 及可能出现的Error处理
  • 除此之外, 这篇博客: 深度剖析Excel表拆分的三项技术(已实现纯Openpyxl保留全部样式拆分,自适应单文件和多文件拆分等)中的 完善能够拆分到多个文件的功能 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 完善后的代码:

    import win32com.client as win32  # 导入模块
    import os
    
    def split_excel(filename, save_name, group_num, title_row=1, excel_app=win32.gencache.EnsureDispatch('Excel.Application')):
        """作者小小明的csdn:https://blog.csdn.net/as604049322"""
        filename = os.path.abspath(filename)
        wb = excel_app.Workbooks.Open(filename)
        try:
            sheet = wb.ActiveSheet
            max_rows = sheet.UsedRange.Rows.Count
            max_cols = sheet.UsedRange.Columns.Count
    
            if title_row > 1:
                start = sheet.Range(sheet.Cells(
                    1, 1), sheet.Cells(title_row-1, max_cols))
            rng = sheet.Range(sheet.Cells(title_row, 1),
                              sheet.Cells(max_rows, max_cols))
            # 设置自动列宽
            rng.EntireColumn.AutoFit()
    
            header = sheet.Range(sheet.Cells(title_row, 1),
                                 sheet.Cells(title_row, max_cols)).Value[0]
            if isinstance(group_num, str):
                for i, value in enumerate(header, 1):
                    if group_num == value:
                        group_num = i
                        break
            names = set(sheet.Range(sheet.Cells(title_row+1, group_num),
                                    sheet.Cells(max_rows, group_num)).Value)
    
            if not save_name.endswith(".xlsx") and not os.path.exists(save_name):
                os.makedirs(save_name)
    
            new_wb = None
            for name, in names:
                if not name:
                    continue
                if save_name.endswith(".xlsx"):
                    new_sheet = excel_app.Sheets.Add(
                        After=wb.Worksheets(wb.Worksheets.Count))
                else:
                    new_wb = excel_app.Workbooks.Add()
                    new_sheet = new_wb.ActiveSheet
                new_sheet.Name = name
                if title_row > 1:
                    wb.Activate()
                    sheet.Activate()
                    start.Copy()
                    if new_wb:
                        new_wb.Activate()
                    new_sheet.Activate()
                    new_sheet.Range("A1").Activate()
                    new_sheet.Paste()
                wb.Activate()
                sheet.Activate()
                rng.AutoFilter(Field=group_num, Criteria1=name)
                rng.Copy()
                if new_wb is not None:
                    new_wb.Activate()
                new_sheet.Activate()
                new_sheet.Range(f"A{title_row}").Activate()
                new_sheet.Paste()
                new_sheet.Range(new_sheet.Cells(1, 1), new_sheet.Cells(
                                1, max_cols)).EntireColumn.AutoFit()
                if not save_name.endswith(".xlsx"):
                    new_wb.SaveAs(os.path.abspath(f"{save_name}/{name}.xlsx"))
                    new_wb.Close()
            sheet.AutoFilterMode = False
            rng.EntireColumn.AutoFit()
            if save_name.endswith(".xlsx"):
                wb.SaveAs(os.path.abspath(save_name))
            else:
                wb.Save()
        finally:
            wb.Close()
    

    分别测试一下:

    image-20210711142757234