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

循环写入文件时运行至约2/3阶段触发OSError(Errno 22)求助

生成千万级测试数据时触发OSError Errno 22问题排查与解决

问题描述

编写了一个用于生成数据库函数测试数据的脚本,需支持1至千万级行数、字符串长度8字符至2GB以上的测试数据。小数据集生成正常,但生成1000万行数据集时,写入到7660799行左右触发Errno 22的OSError,错误指向f.write语句。尝试更换文件扩展名(如txt)后问题依旧,暂未排查内存因素。运行环境为Python 3.10.0、Visual Studio Code 1.54.3、Windows 10(16GB内存)。

原代码如下:

import datetime, VarValues, re
from time import sleep
from os import getcwd, chdir
from random import randint

t0 = datetime.datetime.now()
t1 = re.sub("[-:.]", "", str(t0)).replace(" ", "_")[0:15]

fn = input("File prefix: ")

chdir("H:/Project_DBDev/Python/Testdata")
i = 0
f = open(fn + "_" + t1 + ".txt2", "w")
f.write("Row	Lenght	Value\n")

for j in range(VarValues.r):
    
    print("\n---\n" + str(j + 1) + "\n" + getcwd() + "\n")
    
    v = ""

    for i in range(randint(VarValues.rl,VarValues.rh)):

        ascii_value = randint(VarValues.al,VarValues.ah)
        v = v + chr(ascii_value)

    f.write(str(j + 1) + "\t" + str(len(v)) + "\t" + v + "\n")

    print("Value:\n" + v[0:9] + "...")
    print("\nLenght: " + str(len(v)) + "\n---\n")

f.close()

sleep(4)
t1 = datetime.datetime.now()

print("\nRuntime " + str(int(round((t1 - t0).total_seconds(), 0))) + " seconds\n")
input()

VarValues配置:

# Number of rows.
r = 10000000

# Lower random limit.
rl = 100

# Upper random limit.
rh = 1000

# Lowest ASCII.
al = 97

# Highest ASCII.
ah = 122

原因分析

  • 文件句柄管理不当:直接用open()打开文件后,长时间运行时缓冲区未及时刷新,累积过多数据后触发系统级参数错误(Errno 22对应无效参数)。
  • 低效字符串拼接:循环中用v = v + chr(ascii_value)拼接字符串,每次生成新字符串,大量占用内存,间接干扰文件写入操作。
  • 过量控制台输出:每一行都打印大量内容,占用系统IO资源,拖慢脚本运行并影响文件写入稳定性。

解决方案

  1. 用with语句管理文件:自动处理文件打开/关闭,确保缓冲区及时刷新,避免资源泄漏。
  2. 优化字符串生成:用random.choices结合str.join替代循环拼接,提升效率并减少内存占用。
  3. 减少控制台输出:仅在关键节点打印进度,避免每一行都输出。
  4. 定期刷新缓冲区:循环中定期调用flush(),确保数据及时写入磁盘。
  5. 检查磁盘空间:确认目标磁盘有足够空间(1000万行平均每行550字符,约需5.5GB空间)。

修改后的代码

import datetime
import VarValues
import re
from time import sleep
from os import getcwd, chdir
from random import randint, choices
from string import ascii_lowercase

t0 = datetime.datetime.now()
t1 = re.sub("[-:.]", "", str(t0)).replace(" ", "_")[0:15]

fn = input("File prefix: ")

chdir("H:/Project_DBDev/Python/Testdata")

# 使用with语句自动管理文件,设置1MB缓冲区平衡效率与内存占用
with open(f"{fn}_{t1}.txt", "w", buffering=1024*1024) as f:
    f.write("Row\tLength\tValue\n")
    
    for j in range(VarValues.r):
        # 每10万行打印一次进度,减少控制台IO
        if (j + 1) % 100000 == 0:
            print(f"已写入 {j+1} 行 - 当前目录: {getcwd()}")
        
        # 用choices生成随机字符串,效率远高于循环拼接
        str_len = randint(VarValues.rl, VarValues.rh)
        v = ''.join(choices(ascii_lowercase, k=str_len))
        
        # 写入数据
        f.write(f"{j+1}\t{str_len}\t{v}\n")
        
        # 每10万行刷新一次缓冲区,避免数据累积
        if (j + 1) % 100000 == 0:
            f.flush()

t1 = datetime.datetime.now()
print(f"\n运行时长: {int(round((t1 - t0).total_seconds(), 0))} 秒")
input()

额外说明

  • 用string.ascii_lowercase替代手动生成ASCII字符,代码更简洁不易出错。
  • 移除不必要的sleep(4),脚本结束后直接显示运行时长。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:45:28