uuid – 汎用一意識別子

目的:RFC 4122 準拠の汎用一意識別子を実装する uuid モジュール
利用できるバージョン:2.5 以上

RFC 4122 はセントラルレジストラを必要としない方法でリソースの汎用一意識別子を作成するためのシステムを定義します。UUID は128ビット長で “空間と時間を交差して一意性を保証することができます” 。UUID はドキュメント、ホスト、アプリケーションクライアントや一意な値が必要な様々な状況において識別子に便利です。具体的に言うと、その RFC は Uniform Resource Name 名前空間を作成することを対象とします。

3つのメインアルゴリズムがその仕様により適用されます。

  • 一意性のソースとして IEEE 802 MAC アドレスを使用する
  • 疑似乱数を使用する
  • 暗号ハッシュで組み合わせてよく知られた文字列を使用する

全てのケースにおいて、その種の値はシステムクロックと(そのクロックが後進的にセットされたときに一意性を維持するために)クロックシーケンスの値を組み合わせます。

UUID 1 - IEEE 802 MAC アドレス

UUID バージョン1の値はホストの MAC アドレスを使用して算出されます。 uuid モジュールはシステムから MAC アドレスを取得するために getnode() を使用します。

import uuid

print hex(uuid.getnode())
$ python uuid_getnode.py
0x70cd60f2c980

もしシステムが1つ以上のネットワークカードを持ち、1つ以上の MAC アドレスがあるなら、その値のどれか1つが返されます。

ホストの UUID を生成するには、その MAC アドレスで識別される uuid1() 関数を使用してください。ノード識別子を渡すか、 getnode() が返す値を使用するためにそのフィールドを空白にすることができます。

import uuid

u = uuid.uuid1()

print u
print type(u)
print 'bytes   :', repr(u.bytes)
print 'hex     :', u.hex
print 'int     :', u.int
print 'urn     :', u.urn
print 'variant :', u.variant
print 'version :', u.version
print 'fields  :', u.fields
print '\ttime_low            : ', u.time_low
print '\ttime_mid            : ', u.time_mid
print '\ttime_hi_version     : ', u.time_hi_version
print '\tclock_seq_hi_variant: ', u.clock_seq_hi_variant
print '\tclock_seq_low       : ', u.clock_seq_low
print '\tnode                : ', u.node
print '\ttime                : ', u.time
print '\tclock_seq           : ', u.clock_seq

返される UUID オブジェクトのコンポーネントは読み込み専用インスタンス属性を経由してアクセスされます。 hex, inturn のような属性は UUID の別の表現方法です。

$ python uuid_uuid1.py
eb118663-791f-11e2-a2c4-70cd60f2c980
<class 'uuid.UUID'>
bytes   : '\xeb\x11\x86cy\x1f\x11\xe2\xa2\xc4p\xcd`\xf2\xc9\x80'
hex     : eb118663791f11e2a2c470cd60f2c980
int     : 312459573780010547787799707915419568512
urn     : urn:uuid:eb118663-791f-11e2-a2c4-70cd60f2c980
variant : specified in RFC 4122
version : 1
fields  : (3943794275L, 31007L, 4578L, 162L, 196L, 124027397130624L)
        time_low            :  3943794275
        time_mid            :  31007
        time_hi_version     :  4578
        clock_seq_hi_variant:  162
        clock_seq_low       :  196
        node                :  124027397130624
        time                :  135804116769277539
        clock_seq           :  8900

時間コンポーネントにより uuid1() が呼び出される毎に新しい値が返されます。

import uuid

for i in xrange(3):
    print uuid.uuid1()

(文字列の最初の方にある)時間コンポーネントのみが変更されるこの出力に注意してください。

$ python uuid_uuid1_repeat.py
eb17eba6-791f-11e2-998f-70cd60f2c980
eb190bdc-791f-11e2-80f7-70cd60f2c980
eb190d26-791f-11e2-bb86-70cd60f2c980

あなたのコンピュータは私のものとは違う MAC アドレスを持っているので、そのサンプルをあなたが実行すると全く違う値が表示されます。UUID の最後にあるノード識別子も同様に変更されるでしょう。

import uuid

node1 = uuid.getnode()
print hex(node1), uuid.uuid1(node1)

node2 =  0x1e5274040e
print hex(node2), uuid.uuid1(node2)
$ python uuid_uuid1_othermac.py
0x70cd60f2c980 eb1f026b-791f-11e2-b4c6-70cd60f2c980
0x1e5274040e eb1f6d23-791f-11e2-bdc6-001e5274040e

UUID 3 と 5 - 名前ベースの値

乱数や時間ベースの値の代わりに名前から UUID を作成するためのコンテキストも便利です。UUID 仕様のバージョン3と5は “名前” (DNS ホスト名, URL, オブジェクト id 等) と名前空間特有の種の値を組み合わせるために暗号ハッシュ値(MD5 または SHA-1)を使用します。あらかじめ定義された UUID の値により識別される、DNS, URL, ISO OID や X.500 Distinguished Names と連携するよく知られた名前空間があります。

DNS 名から UUID を作成するには、 uuid3() または uuid5() の名前空間引数として uuid.NAMESPACE_DNS を渡してください。

import uuid

hostnames = ['www.doughellmann.com', 'blog.doughellmann.com']

for name in hostnames:
    print name
    print '\tMD5   :', uuid.uuid3(uuid.NAMESPACE_DNS, name)
    print '\tSHA-1 :', uuid.uuid5(uuid.NAMESPACE_DNS, name)
$ python uuid_uuid3_uuid5.py
www.doughellmann.com
        MD5   : bcd02e22-68f0-3046-a512-327cca9def8f
        SHA-1 : e3329b12-30b7-57c4-8117-c2cd34a87ce9
blog.doughellmann.com
        MD5   : 9bdabfce-dfd6-37ab-8a3f-7f7293bcf111
        SHA-1 : fa829736-7ef8-5239-9906-b4775a5abacb

名前空間で与えられた名前の UUID の値は、いつ、どこで算出されたとしても常に同じです。異なる名前空間による同じ名前の値は違います。

import uuid

for i in xrange(3):
    print uuid.uuid3(uuid.NAMESPACE_DNS, 'www.doughellmann.com')
$ python uuid_uuid3_repeat.py
bcd02e22-68f0-3046-a512-327cca9def8f
bcd02e22-68f0-3046-a512-327cca9def8f
bcd02e22-68f0-3046-a512-327cca9def8f

UUID 4 - ランダムな値

ホストベースや名前空間ベースの UUID の値は “全然違うものではない” ときがあります。例えば、ある探索キーとして UUID を使用したい状況では、ハッシュテーブルの衝突を避けるためにランダムな値のシーケンスに違いがあるほど望ましいです。また少数の汎用ダイジェストで値を持つこともログファイルではその値を見つけ易くなります。UUID に全然違う値を追加するには、ランダムな入力値を使用して生成する uuid4() を使用してください。

import uuid

for i in xrange(3):
    print uuid.uuid4()
$ python uuid_uuid4.py
41ddd08a-383c-49d4-8491-6d66bb41e6a1
c5b0018e-efab-47ed-b1c4-ec100b334a1d
989a52b9-d2c0-415a-af6f-e412c0e31f33

UUID オブジェクトと連携する

新たな UUID を生成することに加えて、UUID オブジェクトを作成するために様々なフォーマットの文字列を構文解析することができます。そうすることで対象の値の比較やソートが簡単になります。

import uuid

def show(msg, l):
    print msg
    for v in l:
        print '\t', v
    print

input_values = [ 
    'urn:uuid:f2f84497-b3bf-493a-bba9-7c68e6def80b',
    '{417a5ebb-01f7-4ed5-aeac-3d56cd5037b0}',
    '2115773a-5bf1-11dd-ab48-001ec200d9e0',
    ]

show('input_values', input_values)

uuids = [ uuid.UUID(s) for s in input_values ]
show('converted to uuids', uuids)

uuids.sort()
show('sorted', uuids)
$ python uuid_uuid_objects.py
input_values
        urn:uuid:f2f84497-b3bf-493a-bba9-7c68e6def80b
        {417a5ebb-01f7-4ed5-aeac-3d56cd5037b0}
        2115773a-5bf1-11dd-ab48-001ec200d9e0

converted to uuids
        f2f84497-b3bf-493a-bba9-7c68e6def80b
        417a5ebb-01f7-4ed5-aeac-3d56cd5037b0
        2115773a-5bf1-11dd-ab48-001ec200d9e0

sorted
        2115773a-5bf1-11dd-ab48-001ec200d9e0
        417a5ebb-01f7-4ed5-aeac-3d56cd5037b0
        f2f84497-b3bf-493a-bba9-7c68e6def80b

See also

uuid
本モジュールの標準ライブラリドキュメント
RFC 4122
汎用一意識別子(UUID) URN 名前空間
Bookmark and Share