Python:在哪里是random.random()seeded? [英] Python: where is random.random() seeded?
问题描述
说我有一些python代码:
import random
r = random.random()
一般来说,r种子的值在哪里?
如果我的操作系统没有随机,那么它在哪里种子?
为什么不推荐用于加密?
按照 da code p>
要查看系统中随机
模块的位置,您只需在终端中执行:
>>> import random
>>>> random .__ file__
'/usr/lib/python2.7/random.pyc'
这为你提供了 .pyc
(编译的)文件的路径,它通常与原来的 .py
其中可以找到可读代码。
让我们看看 /usr/lib/python2.7/random.py
中发生了什么:
你会看到它创建了一个 Random
类的实例,然后(在文件的底部) 该实例的方法到模块函数。整洁的技巧。当在任何地方导入 random
模块时,创建该 Random
类的新实例,然后初始化其值,方法重新分配为模块的函数(使其在每次导入的基础上非常随机)
_inst = Random ()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
triangular = _inst.triangular
randint = _inst.randint
Random
code> __ init __ 方法正在播种:
class Random(_random.Random):
...
def __init __(self,x = None):
self.seed(x)
...
_inst = Random b seed = _inst.seed
所以...如果 x
是无
(没有指定种子)?好吧,让我们检查 self.seed
方法:
def seed self,a = None):
从hashable对象初始化内部状态
当前时间或操作中没有或没有参数种子
系统特定随机源if
如果a不是None或int或long,则使用hash(a)。
如果a是None:
try:
a = long(_hexlify(_urandom(16)),16)
除了NotImplementedError:
import time
a = long(time.time #use fractional seconds
super(Random,self).seed(a)
self.gauss_next = None
注释已经告诉了发生了什么...这个方法尝试使用操作系统提供的默认随机生成器,如果没有,那么它将使用当前时间作为种子值。
但是,等等...什么是 _urandom(16)
/ p>
好吧,答案在于 random.py
文件的开头:
来自os import urandom as _urandom
来自binascii import hexlify as _hexlify
Tadaaa ...种子是一个16字节的数字,来自 os.urandom
假设我们在一个文明的操作系统,如Linux真实随机数生成器)。 random
模块使用的种子与执行以下操作相同:
>>>> long(bins.ciand.hexlify(os.urandom(16)),16)
46313715670266209791161509840588935391L
为什么指定种子值的原因被认为不是那么大是 random
函数不是真正的随机...他们只是一个非常奇怪的数字序列。但是,对于相同的种子,该序列将是相同的。您可以自己尝试:
>>> import random
>>>> random.seed(1)
>>>> random.randint(0,100)
13
>>>> random.randint(0,100)
85
>>>> random.randint(0,100)
77
无论何时或如何,其中您运行该代码(只要用于生成随机数的算法保持不变),如果您的种子 1
,您将始终获得整数 13
, 85
, 77
的目的(参见关于伪随机数生成的)。另一方面, a href =http://stackoverflow.com/a/20636902/289011>用例,但这实际上是一个理想的功能。
这就是为什么被认为是更好依赖于操作系统的随机数发生器。这些通常是基于硬件中断计算的,这些中断非常非常随机(包括中断用于硬盘读取,由用户键入的键击,移动鼠标...)在Linux中,该操作系统生成器是 / dev / random 。或者,作为一个tad picky, / dev / urandom
(这是Python的 os.urandom
实际使用内部)是(如前所述) / dev / random
使用硬件中断来生成随机序列。如果没有中断, / dev / random
可能会用尽,你可能需要等待一点,直到你可以得到下一个随机数。 / dev / urandom
在内部使用 / dev / random
,但它确保它始终具有随机数。
如果你使用linux,只需在终端上执行 cat / dev / random
borrajax @ borrajax: / tmp $ cat / dev / random
_ + _ ?zta K q ߤk / qSlV { Gzk` #p $ *C F B9 o〜, QH ɭ f ̬po 2oSay I have some python code:
import random
r=random.random()
Where is the value of r seeded from in general?
And what if my OS has no random, then where is it seeded?
Why isn't this recommended for cryptography? Is there some way to know what the random number is?
解决方案 Follow da code.
To see where the random
module "lives" in your system, you can just do in a terminal:
>>> import random
>>> random.__file__
'/usr/lib/python2.7/random.pyc'
That gives you the path to the .pyc
("compiled") file, which is usually located side by side to the original .py
where readable code can be found.
Let's see what's going on in /usr/lib/python2.7/random.py
:
You'll see that it creates an instance of the Random
class and then (at the bottom of the file) "promotes" that instance's methods to module functions. Neat trick. When the random
module is imported anywhere, a new instance of that Random
class is created, its values are then initialized and the methods are re-assigned as functions of the module (making it quite random on a per-import basis)
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
triangular = _inst.triangular
randint = _inst.randint
The only thing that this Random
class does in its __init__
method is seeding it:
class Random(_random.Random):
...
def __init__(self, x=None):
self.seed(x)
...
_inst = Random()
seed = _inst.seed
So... what happens if x
is None
(no seed has been specified)? Well, let's check that self.seed
method:
def seed(self, a=None):
"""Initialize internal state from hashable object.
None or no argument seeds from current time or from an operating
system specific randomness source if available.
If a is not None or an int or long, hash(a) is used instead.
"""
if a is None:
try:
a = long(_hexlify(_urandom(16)), 16)
except NotImplementedError:
import time
a = long(time.time() * 256) # use fractional seconds
super(Random, self).seed(a)
self.gauss_next = None
The comments already tell what's going on... This method tries to use the default random generator provided by the OS, and if there's none, then it'll use the current time as the seed value.
But, wait... What the heck is that _urandom(16)
thingy then?
Well, the answer lies at the beginning of this random.py
file:
from os import urandom as _urandom
from binascii import hexlify as _hexlify
Tadaaa... The seed is a 16 bytes number that came from os.urandom
Let's say we're in a civilized OS, such as Linux (with a real random number generator). The seed used by the random
module is the same as doing:
>>> long(binascii.hexlify(os.urandom(16)), 16)
46313715670266209791161509840588935391L
The reason of why specifying a seed value is considered not so great is that the random
functions are not really "random"... They're just a very weird sequence of numbers. But that sequence will be the same given the same seed. You can try this yourself:
>>> import random
>>> random.seed(1)
>>> random.randint(0,100)
13
>>> random.randint(0,100)
85
>>> random.randint(0,100)
77
No matter when or how or even where you run that code (as long as the algorithm used to generate the random numbers remains the same), if your seed is 1
, you will always get the integers 13
, 85
, 77
... which kind of defeats the purpose (see this about Pseudorandom number generation) On the other hand, there are use cases where this can actually be a desirable feature, though.
That's why is considered "better" relying on the operative system random number generator. Those are usually calculated based on hardware interruptions, which are very, very random (it includes interruptions for hard drive reading, keystrokes typed by the human user, moving a mouse around...) In Linux, that O.S. generator is /dev/random. Or, being a tad picky, /dev/urandom
(that's what Python's os.urandom
actually uses internally) The difference is that (as mentioned before) /dev/random
uses hardware interruptions to generate the random sequence. If there are no interruptions, /dev/random
could be exhausted and you might have to wait a little bit until you can get the next random number. /dev/urandom
uses /dev/random
internally, but it guarantees that it will always have random numbers ready for you.
If you're using linux, just do cat /dev/random
on a terminal (and prepare to hit Ctrl+C because it will start output really, really random stuff)
borrajax@borrajax:/tmp$ cat /dev/random
_+�_�?zta����K�����q�ߤk��/���qSlV��{�Gzk`���#p$�*C�F"�B9��o~,�QH���ɭ�f��̬po�2o
这篇关于Python:在哪里是random.random()seeded?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!