Lorenzo
Lorenzo

Reputation: 4648

Unique SHA-1 digest generation

In Python I'm creating 3 objects each of whom has a unique identifier.

The way I generate this unique identifier in all these objects is the following:

class Foo(object):
    def __init__(self):
        unique_id = hashlib.sha1(str(time.time())).hexdigest()

I create these objects one after the other like this:

a = Foo()
b = Foo()
c = Foo()

All these instances end up having the same unique_id because not enough time lapses between their creation.

I've resorted to putting a sleep(0.1) between object creations but I'm sure there's more elegant ways to solve this problem.

Suggestions?

Upvotes: 2

Views: 791

Answers (3)

Tadeck
Tadeck

Reputation: 137290

You have at least two ways to create unique identifiers:

  1. Use incremental value, usually integer, to generate unique key
  2. Use eg. UUID (Universally Unique Identifier)

Incremental identifiers

The first choice is obvious: whether you do it on the database layer or on the application layer, you need to store information on which identifier was generated last, so you can generate another by incrementing it.

Example solution is here:

>>> class Incremental(object):
    _last_id = 0
    def __init__(self):
        Incremental._last_id += 1
        self.id = Incremental._last_id


>>> class MyClass(Incremental):
    def __repr__(self):
        return 'MyClass with id=%s' % self.id


>>> a = MyClass()
>>> b = MyClass()
>>> c = MyClass()
>>> a, b, c
(MyClass with id=1, MyClass with id=2, MyClass with id=3)

Although take a look at what others proposed - their proposals may be better suited when it comes to incremental IDs.

Universally Unique Identifiers

The second choice is just using proper tool for proper task: UUID is specifically designed to give you unique identifier.

There is a module called UUID bundled with standard Python installation that you can use for this:

>>> import uuid
>>> str(uuid.uuid1())
'0baa65ea-b665-11e1-b721-b80305056d6a'

Translating them into hashes

You can translate both values to SHA-1 hashes, if you wish:

>>> import hashlib
>>> hashlib.sha1(str(1)).hexdigest()
'356a192b7913b04c54574d18c28d46e6395428ab'
>>> hashlib.sha1('0baa65ea-b665-11e1-b721-b80305056d6a').hexdigest()
'46bd64c5f4a81b90539d7302d030e01378ef6d6e'

Upvotes: 3

Fred Foo
Fred Foo

Reputation: 363467

Python objects already have a unique identifier, which is their id. This is only unique as long as the objects stay in existence, though; the id may be reused after an object is deleted.

You can also use the uuid module from the standard library, or just keep a counter in the class:

class Foo(object):
    __COUNT = 0
    # or: __COUNT = random.randint(0, 2**N - 1)

    def __init__(self):
        self.unique_id = self.__COUNT  # or take the SHA1 of the count
        type(self).__COUNT += 1

Upvotes: 5

wallyk
wallyk

Reputation: 57764

How about adding 1 to the first, and 2 to the second?

I don't know python well enough to fix it, but the idea would be to write

a = Foo(0)
b = Foo(1)
c = Foo(2)

and have the class compute

unique_id = hashlib.sha1(str(time.time()+offset)).hexdigest()

Upvotes: 1

Related Questions