Python的uuid.uuid()与C++的std::rand()冲突

5 投票
3 回答
765 浏览
提问于 2025-04-17 23:40

我的软件是用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 个回答

0

你可能需要在你的Python代码中使用 uuid.uuid4()

uuid1() 是根据主机ID、序列号和当前时间生成的,而 uuid4() 是随机生成的。

(不过还有一个问题:如果 uuid1() 确实使用当前时间,那它怎么可能会生成相同的uuid,就像在这里每次第一次运行时看到的那样。)

1

我在这里找到了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

0

我找到了解决这个问题的方法。其实,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

撰写回答