我正在尝试为文件名生成一个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位不同,我认为只有时间派生,这似乎很危险,特别是考虑到我是多处理(所以代码可以在完全相同的时间)。关于这个问题,有没有一些智慧?
答案 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冲突。