21

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()

しかし、それはひどく遅いです(私の3.9GHzSSDディスクマシンのsize_kb=1024の場合は0.82秒)。大きなボトルネックは、ランダムなint生成のようです(randint()を0に置き換えると、実行時間が0.82秒から0.14秒に短縮されます)。

ランダムデータファイル(つまり、dd if = / dev / urandom)を作成するより効率的な方法があることはわかっていますが、好奇心のためにこれを理解しようとしています...これを改善する明白な方法はありますか?

4

2 に答える 2

51

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次に。

(私のユースケースは単体テスト用のファイルを生成するため、他の生成されたファイルと同一ではないファイルが必要です)。

もう1つのオプションは、ファイルにUUID4を書き込むことですが、正確な使用例がわからないため、それが実行可能かどうかはわかりません。

于 2013-01-11T10:43:35.640 に答える
3

作成するPythonコードは、ランダムバイナリファイルの使用方法によって完全に異なります。複数の目的で「かなり良い」ランダム性が必要な場合は、JonClementsのコードがおそらく最適です。

ただし、少なくともLinux OSでは、os.urandomは/ dev / urandomに依存しています。これは、Linuxカーネル(drivers / char / random.c)で次のように記述されています。

/ dev / urandomデバイス[...]は、要求された数のバイトを返します。エントロピープールが再充電する時間を与えずに、ますます多くのランダムバイトが要求されると、これは単に暗号的に強い乱数になります。ただし、多くのアプリケーションでは、これは許容されます。

だから問題は、これはあなたのアプリケーションに受け入れられるかということです。より安全なRNGが必要な場合は、代わりに/ dev/randomでバイトを読み取ることができます。このデバイスの主な不便さ:Linuxカーネルが十分なエントロピーを収集できない場合、無期限にブロックする可能性があります。EGDのような他の暗号的に安全なRNGもあります。

あるいは、実行速度が主な関心事であり、モンテカルロ法に「軽いランダム性」が必要な場合(つまり、予測不可能性は問題ではなく、一様分布は問題ありません)、ランダムバイナリファイルを一度生成して使用することを検討できます。少なくとも開発のために、何度もそれを。

于 2013-01-11T11:21:10.310 に答える