Подтвердить что ты не робот

Создание случайных двоичных файлов

Я пытаюсь использовать python для создания случайного двоичного файла. Это то, что у меня уже есть:

f = open(filename,'wb')
for i in xrange(size_kb):
    for ii in xrange(1024/4):
        f.write(struct.pack("=I",random.randint(0,sys.maxint*2+1)))

f.close()

Но он ужасно медленный (0,82 секунды для size_kb = 1024 на моем 3,9 ГГц дисководе SSD). Большим узким местом, по-видимому, является случайная генерация int (замена randint() на 0 сокращает время работы от 0,82 до 0,14 с).

Теперь я знаю, что есть более эффективные способы создания файлов случайных данных (а именно dd if =/dev/urandom), но я пытаюсь понять это ради любопытства... есть ли очевидный способ улучшить это

4b9b3361

Ответ 1

IMHO - полностью избыточно:

f.write(struct.pack("=I",random.randint(0,sys.maxint*2+1)))

Абсолютно не нужно использовать struct.pack, просто выполните что-то вроде:

import os

with open('output_file', 'wb') as fout:
    fout.write(os.urandom(1024)) # replace 1024 with size_kb if not unreasonably large

Затем, если вам нужно повторно использовать файл для чтения целых чисел, тогда struct.unpack затем.

(мой вариант использования генерирует файл для unit test, поэтому мне просто нужно файл, который не идентичен другим сгенерированным файлам).

Еще один вариант - просто написать UUID4 в файл, но поскольку я не знаю конкретного варианта использования, я не уверен, что он жизнеспособен.

Ответ 2

Код python, который вы должны написать полностью, зависит от того, как вы собираетесь использовать случайный двоичный файл. Если вам просто нужна "довольно хорошая" случайность для нескольких целей, то код Jon Clements, вероятно, лучший.

Однако, по крайней мере, в ОС Linux os.urandom полагается на /dev/urandom, который описан в ядре Linux (drivers/ char/random.c) следующим образом:

Устройство/dev/urandom [...] вернет столько же байтов, сколько и просил. Поскольку все больше и больше случайных байтов запрашиваются без предоставления время перезарядки энтропийного пула приведет к случайным числа, которые просто криптографически сильны. Для многих приложений, однако это приемлемо.

Итак, вопрос в том, приемлемо ли это для вашего приложения? Если вы предпочитаете более безопасный RNG, вы можете читать байты в /dev/random вместо этого. Главное неудобство этого устройства: он может блокироваться бесконечно, если ядро ​​Linux не может собрать достаточно энтропии. Существуют также другие криптографически безопасные RNG, такие как EGD.

В качестве альтернативы, если ваша главная проблема - это скорость выполнения, и если вам просто нужна "легкая случайность" для метода Монте-Карло (т.е. непредсказуемость не имеет значения, равномерное распределение), вы можете подумать о создании своего случайного двоичного файла один раз и использовать его много раз, по крайней мере для разработки.