你的算法是好的(只要你的 DB API 模块是安全的,线程是安全的)并且可能是最好的方法。IntegrityError
它永远不会给您重复(假设您在 sid 上有 PRIMARY 或 UNIQUE 键),但是您在 INSERT 上获得异常的机会微乎其微。但是你的代码看起来不太好。最好使用尝试次数有限的循环而不是递归(如果代码中的某些错误可能会变得无限):
for i in range(MAX_ATTEMPTS):
sid = os.urandom(8).decode('hex')
db.execute('SELECT COUNT(*) FROM sessions WHERE sid=?', (sid,))
if not db.fetchone()[0]:
# You can catch IntegrityError here and continue, but there are reasons
# to avoid this.
db.execute('INSERT INTO sessions (sid) VALUES (?)', (sid,))
break
else:
raise RuntimeError('Failed to generate unique session ID')
您可以增加读取的随机字符数,以使失败的机会更小。base64.urlsafe_b64encode()
如果您想让 SID 更短,是您的朋友,但是您必须确保您的数据库对此列使用区分大小写的比较(MySQL 的 VARCHAR 不适合,除非您为其设置二进制排序规则,但 VARBINARY 是可以的)。