Python多处理与uuid.uuid4()不能很好地协同工作

时间:2010-05-03 16:44:51

标签: python time random multiprocessing uuid

我正在尝试为文件名生成一个uuid,我也在使用多处理模块。令人不快的是,我所有的uuids都完全一样。这是一个小例子:

import multiprocessing
import uuid

def get_uuid( a ):
    ## Doesn't help to cycle through a bunch.
    #for i in xrange(10): uuid.uuid4()

    ## Doesn't help to reload the module.
    #reload( uuid )

    ## Doesn't help to load it at the last minute.
    ## (I simultaneously comment out the module-level import).
    #import uuid

    ## uuid1() does work, but it differs only in the first 8 characters and includes identifying information about the computer.
    #return uuid.uuid1()

    return uuid.uuid4()

def main():
    pool = multiprocessing.Pool( 20 )
    uuids = pool.map( get_uuid, range( 20 ) )
    for id in uuids: print id

if __name__ == '__main__': main()

我偷看了uuid.py的代码,看起来依赖于平台使用一些操作系统级别的例程来实现随机性,所以我对一个python级别的解决方案感到困惑(做一些像重新加载uuid模块或选择一个新的随机种子)。我可以使用uuid.uuid1(),但只有8位不同,我认为只有时间派生,这似乎很危险,特别是考虑到我是多处理(所以代码可以在完全相同的时间)。关于这个问题,有没有一些智慧?

4 个答案:

答案 0 :(得分:5)

如果您需要这样做,这是生成您自己的uuid4的正确方法:

import os, uuid
return uuid.UUID(bytes=os.urandom(16), version=4)

Python应该自动执行此操作 - 当本机_uuid_generate_random不存在时,此代码就在uuid.uuid4之外。您的平台的_uuid_generate_random必定存在问题。

如果你必须这样做,不要自己解决它,让你平台上的其他人受苦; report the bug

答案 1 :(得分:0)

我也没有办法让这项工作成功。但是你可以在主线程中生成所有uuids并将它们传递给worker。

答案 2 :(得分:0)

这对我来说很好。你的Python安装是否有os.urandom?如果没有,随机数播种将非常差并且会导致此问题(假设还没有本机UUID模块,uuid._uuid_generate_random)。

答案 3 :(得分:0)

当前,我正在研究一个脚本,该脚本可以从zip存档或磁盘中获取文件。提取后,有效负载将通过Web API推送到外部工具。 出于性能原因,我使用了multiprocessing.Pool.map方法。对于tmp文件名,uuid看起来非常方便。但是我遇到了您在这里问的同一问题。

首先,请查看uuid中的官方文档。有一个名为is_safe的类属性,如果uuid是否是多进程安全的,它可以提供更多信息。就我而言,不是。

经过一番研究,我终于改变了策略,从uuid转到处理pid和名称。 因为我只需要uuid来命名tmp文件,所以pid和name也可以正常工作。我们可以通过multiprocessing.current_process()访问当前工作者Process实例。如果确实需要uuid,则可以以某种方式集成worker pid。

此外,uuid使用系统entropy进行生成(uuid source)。因为对我而言,文件的命名方式无关紧要,所以该解决方案还可以防止entropy冲突。