Python的uuid.uuid()与C++的std::rand()冲突
我的软件是用C++写的,通过Python脚本(使用Swig)来调用。当在脚本中调用Python函数uuid.uuid1()时,C++中的std::rand()使用的种子似乎丢失了。这是个问题,因为我需要确保我的软件在C++代码中能够以完全相同的方式重新启动(这对uniqid来说不是问题)。
下面的例子简化了这个问题:
C++文件 testrand.h:
#ifndef __INCLUDE__TESTRAND_H__
#define __INCLUDE__TESTRAND_H__
void initialize(unsigned long int seed);
unsigned long int get_number();
#endif
C++文件 testrand.cpp:
#include "testrand.h"
#include <cstdlib>
void initialize(unsigned long int seed)
{
std::srand(seed);
}
unsigned long int get_number()
{
return std::rand();
}
Swig文件 testrand.i:
%module testrand
%{
#include "testrand.h"
%}
%include "testrand.h"
编译是通过以下命令完成的:
swig -python -c++ testrand.i
g++ -c -fPIC testrand.cpp testrand_wrap.cxx -I/usr/include/python2.7/
g++ -shared testrand.o testrand_wrap.o -o _testrand.so
如果我多次运行以下Python测试用例,我会发现第一个数字总是相同的(这是预期的),但是在调用uuid.uuid1()之后生成的第二个数字在每次运行时都不同。
import testrand
import uuid
testrand.initialize(10)
x1 = testrand.get_number()
print x1
uuid.uuid1()
x2 = testrand.get_number()
print x2
多次运行的结果:
> python testcase.py
1215069295
1691632206
> python testcase.py
1215069295
746144017
> python testcase.py
1215069295
377602282
你有没有什么主意,如何在不影响我的C++种子的情况下使用Python的uuid?谢谢!(编辑:我的配置是:Linux openSUSE 12.3,64位,Python 2.7.3(但在2.7.2上也有同样的问题),Swig 2.0.9,gcc 4.7.2(但在4.5.1上也有同样的问题))
3 个回答
你可能需要在你的Python代码中使用 uuid.uuid4()
。
uuid1()
是根据主机ID、序列号和当前时间生成的,而 uuid4()
是随机生成的。
(不过还有一个问题:如果 uuid1()
确实使用当前时间,那它怎么可能会生成相同的uuid,就像在这里每次第一次运行时看到的那样。)
我在这里找到了uuid的代码:http://pythoninside.com/en/source-code/2.7.5/uuid/uuid.py,然后我把代码复制到示例脚本中使用(也就是没有导入uuid)。问题出现在第500行的调用_uuid_generate_time(_buffer)
。这个函数在第402到410行被定义为ctypes.CDLL(ctypes.util.find_library('uuid')).uuid_generate_time
的别名。我找到的关于这个bug的唯一提及是:https://savannah.cern.ch/bugs/?24456
我找到了解决这个问题的方法。其实,C++的种子只会在第一次调用uuid.uuid1()
这个函数时通过uuid模块初始化一次。如果我在我的示例脚本中添加一个没用的第一次调用这个函数,就不会出现这个问题了:
import testrand
import uuid
uuid.uuid1()
testrand.initialize(10)
x1 = testrand.get_number()
print x1
uuid.uuid1()
x2 = testrand.get_number()
print x2