首页 > 解决方案 > 使用 Python 3+ 在文件中写入 150 万行

问题描述

我正在尝试将 sql 语句写入 sql 文件以创建 10,000 个表。每个表包含 5 列,每列包含 150 万行数据。

text_file = open("D:\Output.sql", "a", encoding="utf-8")
count = 0
for i in range(1,10001):
    a=[]
    b=[]
    x='Tab_'+str(i)

    a.append(random.choice(name)+'_'+str(i))
    a.append(random.choice(ssn)+'_'+str(i))
    a.append(random.choice(address)+'_'+str(i))
    a.append(random.choice(dob)+'_'+str(i))
    a.append(random.choice(phone)+'_'+str(i))

    text_file.write('create table Python_test.'+ x + '(' +
                    a[0] + ' VARCHAR(255),' + 
                    a[1] +' VARCHAR(255),' + 
                    a[2] +' VARCHAR(255),' + 
                    a[3] +' VARCHAR(255),' + 
                    a[4] +' VARCHAR(255));\n')
    #print('\n')

    for j in range(1,1500001):
        #print(i)
        #print(a)
        text_file.write('insert into '+ x + '('   + 
                         a[0]+','+a[1]+','+a[2]+','+a[3]+','+a[4]+
                        ') values (\''+ 
                        fake.name()+'\',\''+rstr.xeger(random.choice(sList))+'\',\''+
                        fake.address()+'\',\''+rstr.xeger(random.choice(dbList))+'\',\''+
                        rstr.xeger(random.choice(pList))+'\');\n')


    text_file.write('\n')
    count=count+1
    print(count)


text_file.close()

2个for循环需要很多时间。有什么方法可以优化这段代码以最小化执行这段代码所花费的时间吗?

标签: python-3.x

解决方案


一些建议,不是一个完整的解决方案。

不要连接字符串。写入文件已经将它们连接起来。考虑:

def write_all(f, *pieces):
  for piece in pieces:
    f.write(piece)

# Now you can:

write_all(
  text_file,
  'create table Python_test.', x, '(', 
  a[0], ' VARCHAR(255),',
  # etc ad libitum.
  ');\n'
)

同时,您可以取消a[0], etc 并很好地命名事物,并且str(i)只计算一次。

以二进制形式打开您的输出文件(这样您就无需在通用换行符转换或编码检查上花费任何时间),最重要的是,使用大缓冲区:

with open("file.sql", "wb", 4000000) as text_ file:
  # Do your generation here

运行多个进程,针对不同的子范围i,并行写入不同的物理设备。我想代码是 I/O 密集型的,主要是等待写入完成。几个并行进程可以生成更多数据,而来自不同进程的前一部分被文件系统消耗;multiprocessing模块应该让它变得简单。

但不要指望奇迹。您正在生成 10k 个文件,每个文件数 MB,这是数十 GB 的数据。即使是最快的 m.2 SSD ,需要一些时间来解决磁盘问题,尤其是考虑到(不是很快)NTFS 文件系统。

在慢速磁盘上,将输出传递到 可能很有用gzip,因为它是生成的,这样可以减少磁盘上的字节数。考虑到大量的公共子字符串,它应该可以很好地压缩。然后,您可以在向您正在测试的数据库提供数据的同时即时解压缩文件(因为它还能是什么?...)。


推荐阅读