如何生成100万个随机整数并将它们写入文件?

时间:2011-10-06 07:52:07

标签: python file-io random

我试图对我的外部排序算法进行一些测试,我认为我应该生成大量的随机数并将它们放入文件中。

我是这样做的:

import tempfile, random

nf = tempfile.NamedTemporaryFile(delete=False)
i = 0
while i < 1000:
    j = 0
    buf = ''
    while j < 1000:
        buf += str(random.randint(0, 1000))
        j += 1
    nf.write(buf)
    i += 1

我想,我应该通过减少文件IO操作来加快生成过程,所以我使用buf来存储尽可能多的数字,然后将buf写入文件。

问题:

我仍然感觉到,生成和编写过程很慢。

我出错了吗?

修改

在C ++中,我们可以简单地将intfloat写入<<文件,而不将converting them写入字符串。

那么我们可以在Python中做同样的事情吗?我的意思是将整数写入文件而不将其转换为str。

6 个答案:

答案 0 :(得分:7)

操作系统已针对此类I / O操作进行了优化。因此,您可以直接将数字写入文件并获得非常好的速度:

import tempfile, random

with tempfile.NamedTemporaryFile(delete=False) as nf:
    for _ in xrange(1000000):  # xrange() is more efficient than range(), in Python 2
        nf.write(str(random.randint(0, 1000)))

实际上,只有在大小优化的文件缓冲区已满时,才会将数字写入磁盘。问题中的代码和上面的代码在我的机器上同时进行。所以,我建议使用我更简单的代码并依赖操作系统的内置优化。

如果结果适合内存(100万个数字就是这种情况),那么你可以通过创建最终字符串然后一次性编写来保存一些I / O操作:

with tempfile.NamedTemporaryFile(delete=False) as nf:
    nf.write(''.join(str(random.randint(0, 1000)) for _ in xrange(1000000)))

第二种方法在我的计算机上快了30%(2.6秒而不是3.8秒),这可能要归功于单次写入调用(而不是一百万write()次调用 - 实际磁盘写入可能少得多)

你的问题的“许多大写”方法落在中间(3.1秒)。但是它可以改进:它更清晰,更Pythonic写这样:

import tempfile, random

with tempfile.NamedTemporaryFile(delete=False) as nf:
    for _ in xrange(1000):
        nf.write(''.join(str(random.randint(0, 1000)) for _ in xrange(1000)))

这个解决方案相当于原始问题中的代码(比我原来的2.6秒,而不是3.8秒)。

总之,上面的第一个简单方法对您来说可能足够快。如果不是,并且整个文件可以适合内存,第二种方法既快速又简单。否则,你最初的想法(更少的写入,更大的块)是好的,因为它与“单一写入”方法一样快,并且仍然非常简单,如上所述。

答案 1 :(得分:3)

不要在循环中使用字符串连接。请改用str.join

  

CPython实现细节:如果s和t都是字符串,某些Python实现(如CPython)通常可以对s = s + t或s + = t形式的赋值执行就地优化。如果适用,此优化使得二次运行时间的可能性大大降低。此优化依赖于版本和实现。对于性能敏感的代码,最好使用str.join()方法,该方法确保跨版本和实现的一致的线性串联性能。

您的代码如下所示:

buf = ''.join(str(random.randint(0, 1000)) for j in range(1000))

请注意,由于您尚未指定分隔符,因此它将如下所示:

3847018274193258124003837134....

如果您希望数字(例如)以逗号分隔,请将''更改为','

我也认为你不需要缓冲自己,因为写入文件应该已经缓冲了。

答案 2 :(得分:2)

如果你只需要生成一些随机数并且你在Linux下,请尝试shell命令

for i in {1..1000000}; do echo $[($RANDOM % 1000)]; done > test.in

好的,我在下面测试这段代码,完成后需要大约5秒钟

import tempfile, random

nf = tempfile.NamedTemporaryFile(delete=False)
for i in xrange(0, 1000000):
    nf.write(str(random.randint(0, 1000)))

答案 3 :(得分:1)

我不确定Python,但+ =通常是一个昂贵的操作,因为它将字符串复制到新的内存。

使用您加入的某些字符串构建器或数组可能要快得多。

答案 4 :(得分:1)

喜欢这个

import random
import struct

with open('binary.dat','wb') as output:
     for i in xrange(1000000):
         u = random.randint(0,999999) # number
         b = struct.pack('i', u) # bytes
         output.write(b)

这将创建400万字节的数据。 100万个4字节值。

您可以在struct阅读以及各种打包选项:http://docs.python.org/library/struct.html

答案 5 :(得分:-2)

做一百万件事情会相对缓慢。此外,根据您想要数字的随机性,您可能希望投资更强大的随机整数生成器。这是个人的最爱:http://en.wikipedia.org/wiki/Mersenne_twister