uuid.SafeUUID
A "safe" UUID was generated with synchronization that guarantees no two processes get the same one. Only uuid1 can know, and only when the platform's uuid_generate_time_safe reports it; every other UUID, and most uuid1 values in practice, say unknown.
Common call
u.is_safe is uuid.SafeUUID.safe
Returns
True / False
Replaces
Guessing whether uuid1 is unique across processes
Watch out
unknown is the usual value; it does not mean unsafe
class uuid.SafeUUID(Enum)
→ SafeUUID
Demo
Live evaluation
SafeUUID(value) returns the member with that value.
Try:
Inputs
valueint0, -1 …
Code
import uuid uuid.SafeUUID(0)
Result
<SafeUUID.safe: 0>
Lookup by value accepts only 0, -1 and None; anything else, including the string 'safe', raises ValueError. Use SafeUUID['safe'] or SafeUUID.safe for names. A UUID you construct yourself always reports SafeUUID.unknown unless you pass is_safe=.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| value | int | None | yes | SafeUUID(value) looks a member up by value: 0, -1 or None. SafeUUID[name] looks it up by name. |
Return value
SafeUUID — One of the three members.
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| SafeUUID.safe | SafeUUID | Value 0: the platform generated the UUID in a multiprocessing-safe way. |
| SafeUUID.unsafe | SafeUUID | Value -1: it was not generated in a multiprocessing-safe way. |
| SafeUUID.unknown | SafeUUID | Value None: the platform does not say. |
| UUID.is_safe | SafeUUID | Read-only attribute of every UUID (a __slots__ entry); set by the is_safe= keyword of UUID(), default SafeUUID.unknown. |
| uuid.Enum | type | Not an API: enum.Enum, imported by uuid.py to define SafeUUID, so it shows up as a public module attribute. Import it from enum. |
Common patterns
Insist on safe uuid1 values
Fall back to uuid4 when the platform cannot promise uniqueness across processes.
import uuid u = uuid.uuid1() if u.is_safe is not uuid.SafeUUID.safe: u = uuid.uuid4()
Carry the flag through storage
Pickling keeps is_safe; for your own formats store is_safe.value and restore with SafeUUID(value).
import uuid row = {'id': u.hex, 'safe': u.is_safe.value} back = uuid.UUID(row['id'], is_safe=uuid.SafeUUID(row['safe']))
Examples
1. The three members
import uuid
list(uuid.SafeUUID)
Returns
[<SafeUUID.safe: 0>, <SafeUUID.unsafe: -1>, <SafeUUID.unknown: None>]2. Default for any UUID
import uuid
uuid.UUID(int=1).is_safe
Returns
<SafeUUID.unknown: None>3. uuid4 does not say
import uuid
uuid.uuid4().is_safe
Returns
<SafeUUID.unknown: None>4. Set it when constructing
import uuid
uuid.UUID(int=1, is_safe=uuid.SafeUUID.safe).is_safe
Returns
<SafeUUID.safe: 0>5. unknown has the value None
import uuid
uuid.SafeUUID['unknown'].value is None
Returns
True6. A plain Enum, not an IntEnum
import uuid
uuid.SafeUUID.safe == 0
Returns
False7. uuid.Enum is enum.Enum
import uuid, enum
uuid.Enum is enum.Enum
Returns
TruePitfalls
1. Comparing is_safe with 0
SafeUUID is a plain Enum: members are never equal to their values. Compare with the member.
is_safe == 0
import uuid uuid.UUID(int=1, is_safe=uuid.SafeUUID.safe).is_safe == 0
False
is SafeUUID.safe
import uuid uuid.UUID(int=1, is_safe=uuid.SafeUUID.safe).is_safe is uuid.SafeUUID.safe
True
2. Reading unknown as unsafe
unknown means the platform gave no information, which is the normal case. The value None is also falsy, unlike unsafe (-1).
not value
import uuid not uuid.uuid4().is_safe.value
True
compare members
import uuid uuid.uuid4().is_safe is uuid.SafeUUID.unsafe
False
3. Changing is_safe later
UUIDs are immutable, is_safe included. Build a new UUID with is_safe=.
assign
import uuid u = uuid.UUID(int=1) u.is_safe = uuid.SafeUUID.safe
TypeError: UUID objects are immutable
new UUID
import uuid u = uuid.UUID(int=1) uuid.UUID(int=u.int, is_safe=uuid.SafeUUID.safe).is_safe
<SafeUUID.safe: 0>
When to use
Use it
- Deciding whether uuid1 values from several processes on one machine can collide
Reach for something else
- uuid4, uuid3, uuid5 → always unknown, and uniqueness does not depend on it
- Using uuid.Enum in your code → import Enum from enum
Notes
CPython impl
Defined with @_simple_enum(Enum) in Lib/uuid.py. uuid1 sets it from the second result of _uuid.generate_time_safe() when the _uuid extension provides it and neither node nor clock_seq is given
In practice
On the two machines used to check this page (Windows CPython 3.13, Ubuntu WSL CPython 3.12) uuid._generate_time_safe was None, so uuid1().is_safe was SafeUUID.unknown
Pickling
UUID.__getstate__ stores is_safe.value only when it is not unknown, so pickles stay readable by Pythons older than 3.7
uuid.Enum
Shows up in dir(uuid) because uuid.py does from enum import Enum and the module has no __all__ (checked on 3.13)
FAQ
The platform did not report whether the UUID was generated in a multiprocessing-safe way. It is the default for every UUID and the usual result of uuid1.