2016-05-20 11 views
3

ランダムバイトをbytearrayまたはバイトとして取得することをお探しですか、os.urandomと同じです。Pythonのランダムモジュールを使用して、os.urandomの予測可能な置き換えがありますか?

しかし、値が再現可能になるようにランダムなシードを設定できる必要があります。

def urandom_from_random(rng, length): 
    return bytes([rng.randint(0, 255) for i in range(length)]) 

import random 
rng = random.Random(42) 
data = urandom_from_random(rng, 120) 
print(data) 

上記のスクリプトは機能しますが、あまり効率的ではありません。

多くのintを作成してバイトに変換するだけでなく、これを行うより直接的な方法はありますか?


注:

  • urandomのは、予測可能な結果を​​返す作りはpossible on Linuxですが、rootアクセスを必要とします。

答えて

0

あなたのコードの初めにシードを使用します。

import random 
random.seed(7) 
rng = random.Random(42) 
data = urandom_from_random(rng, 120) 

限り、あなたは、あなたが同じランダムピックを持ってシードに7を使用して。次に、任意の値に変更することができます。

+0

は 'random.seed(7)'必要とされません。このスクリプトは、そのままの状態で動作し、私の質問を明確にしました。 – ideasman42

+0

ok then random.getrandbits(N)? – Vince

2

randomの中で最も近い機能は、getrandbitsです。要求されたビット数の整数を返します。 bytesインスタンスに変換する場合は、int.to_bytesを使用できます。

は、ここでそのペアこれら二つ一緒に素早く機能です:あなたはto_bytesに指定

def urandom_from_random(rng, length): 
    if length == 0: 
     return b'' 
    integer = rng.getrandbits(length * 8) 
    result = integer.to_bytes(length, sys.byteorder) 
    return result 

バイト順序は問題ないはず。私は、システムのネイティブバイトオーダーを使用するように指示しますが、そうでない場合より速くなるかどうかは実際にはわかりません。

+0

'random.getrandbits()'はMersenne Twisterアルゴリズム(MT19937)によって生成された32ビットの単語を結合するために "リトルエンディアン"を内部的に使用します。 – jfs

+0

これはintの最大サイズによって制限され、大きい値では、 'OverflowError:符号付き整数が最大値を超えています'という例外が発生します。 – ideasman42

+0

その例外を取得するために何バイト必要ですか? Pythonの 'int'型は可変サイズなので、サイズに関係なく動作します。私は長さの値が問題なく1万までテストしました。あなたは私の実際のコード、またはいくつかのバリエーションを実行していますか?あなたは何かエラーを導入していませんか?あなたが言及した 'int'値に対してあまりにも短いバイト長を与えると' int.to_bytes'が発生させる例外です。 – Blckknght

0

これはgetrandbitsの内部INT_MAXの制限を考慮した@ Blckknghtの回答の修正版です。

def urandom_from_random(rng, length): 
    if length == 0: 
     return b'' 

    import sys 
    chunk_size = 65535 
    chunks = [] 
    while length >= chunk_size: 
     chunks.append(rng.getrandbits(
       chunk_size * 8).to_bytes(chunk_size, sys.byteorder)) 
     length -= chunk_size 
    if length: 
     chunks.append(rng.getrandbits(
       length * 8).to_bytes(length, sys.byteorder)) 
    result = b''.join(chunks) 
    return result 

使用例:

import random 
rng = random.Random(42) 
print(len(urandom_from_random(rng, 300000000))) 
関連する問題