La plus courte de hachage en python pour le nom des fichiers de cache
Quel est le plus court de hachage (dans le nom de fichier-forme utilisable, comme un hexdigest) disponibles en python? Mon application veut sauver fichiers de cache pour certains objets. L'objet doit être unique repr() de sorte qu'ils sont utilisés pour "graine" le nom de fichier. Je veux produire, éventuellement, un nom de fichier unique pour chaque objet (pas tant que ça). Ils ne doivent pas entrer en collision, mais si ils ne mon application va tout simplement un manque de cache pour cet objet (et aura pour réindexer que les données de l'objet, un mineur le coût de l'application).
Donc, si il ya une collision de nous perdre un fichier de cache, mais c'est le collectées épargne de la mise en cache tous les objets qui rend l'application de démarrage beaucoup plus rapide, donc il n'a pas beaucoup d'importance.
Droit maintenant, je suis en fait en utilisant de l'abs(de hachage(repr(obj))); c'est le droit, la chaîne de hachage! N'ai pas trouvé de collisions, mais je voudrais avoir une meilleure fonction de hachage. hashlib.md5 est disponible dans la bibliothèque python, mais le hexdigest est très long si on les mettait dans un nom de fichier. Des solutions de rechange raisonnables de collision de la résistance?
Edit:
Cas d'utilisation est comme ceci:
Le chargeur de données obtient une nouvelle instance d'un transport de données objet. Types uniques ont unique repr. donc, si un fichier de cache pour hash(repr(obj))
existe, je unpickle que le cache de fichier et de le remplacer obj avec le unpickled objet. Si il y avait une collision et que le cache était un faux match que j'ai un avis. Donc, si nous n'avons pas de cache ou ont un faux match, j'ai plutôt init obj (rechargement de ses données).
Conclusions (?)
La str
de hachage en python peut être assez bon, je ne s'inquiète de sa collision de la résistance. Mais si je peux hachage 2**16
objets avec elle, il va être plus que suffisant.
J'ai trouvé comment prendre un hex de hachage à partir de toute source de hachage) et de le stocker de manière compacte avec base64:
# 'h' is a string of hex digits
bytes = "".join(chr(int(h[i:i+2], 16)) for i in xrange(0, len(h), 2))
hashstr = base64.urlsafe_b64encode(bytes).rstrip("=")
- Pourquoi se soucier de la longueur des noms de fichiers? Ce n'est pas grave du tout, sauf si vous utilisez un muet système de fichiers
- Qu'il est laid. Et tous les programmeurs qui veulent exprimer moins avec plus, et là je sais que je peux, plein de hachage cryptographique est exagéré.
- dans le dernier exemple, pour un python hashlib de hachage, vous pouvez utiliser octets = (..).digest() de cours.
- Vous ne devez pas utilisez la fonction de hachage car il n'est pas garanti d'être persistant à travers des sessions (ou architectures, même si elle peut être sans importance pour votre cas si tous les fichiers de cache sont stockées localement). En fait, commencer avec Python 3.3, c'est la garantie d'être randomisés pour cordes. Vous devriez envisager d'utiliser écrite à la main à des fonctions telles que ceci.
Vous devez vous connecter pour publier un commentaire.
La le paradoxe d'anniversaire s'applique: étant donné une bonne fonction de hachage, le nombre attendu de hachages avant qu'une collision se produit est d'environ sqrt(N), où N est le nombre de valeurs différentes que la fonction de hachage peut prendre. (L'entrée de wikipedia que j'ai pointé donne la formule exacte). Ainsi, par exemple, si vous souhaitez ne pas utiliser plus de 32 bits, votre soucis de collision sont graves pour environ 64 KO objets (c'est à dire,
2**16
objets -- la racine carrée de la2**32
différentes valeurs de votre fonction de hachage peut prendre). Combien d'objets vous attendez-vous à avoir, comme un ordre de grandeur?Puisque vous mentionnez qu'une collision est un problème mineur, je vous recommande de viser une longueur de hachage qui est à peu près le carré du nombre d'objets que vous aurez, ou un peu moins, mais pas BEAUCOUP moins que cela.
Vous voulez faire un nom de fichier, c'est que sur la casse du système de fichiers, comme typique sur Unix, ou avez-vous à répondre à la casse des systèmes de trop? C'est important parce que vous visez pour les noms de fichiers courts, mais le nombre de bits par caractère que vous pouvez utiliser pour représenter votre hachage comme un nom de fichier change de façon spectaculaire sur le cas-sensive vs insensible systèmes.
Sur la casse du système, vous pouvez utiliser la bibliothèque standard du
base64
module (je recommande le "urlsafe" version de l'encodage, c'est à dire cette fonction, d'éviter les '/' caractères qui pourraient être présentes dans la plaine base64 est important dans les noms de fichiers Unix). Cela vous donne 6 bits utilisable par caractère, beaucoup mieux que les 4 bits/char dans l'hex.Même sur la casse du système, vous pouvez toujours faire mieux que hex -- utilisation en base64.b32encode et obtenez 5 bits par caractère.
Ces fonctions prennent et renvoient des chaînes; utiliser le
struct
module pour transformer des chiffres en chaînes si votre choix de la fonction de hachage génère des nombres.Si vous avez quelques dizaines de milliers d'objets, je pense que vous serez très bien avec builtin de hachage (32 bits, 6-7 caractères en fonction de votre choix de l'encodage). Pour un million d'objets que vous aimeriez 40 bits ou (7 ou 8 caractères) -- vous pouvez plier (xor, ne pas tronquer;-) un sha256 vers le bas pour un long avec un nombre raisonnable de bits, dire 128, et utiliser le
%
opérateur de réduire encore plus pour la longueur souhaitée avant le codage.La builtin fonction de hachage de chaînes est assez libre de collision, et aussi assez court. Il a
2**32
valeurs, de sorte qu'il est assez peu probable que vous rencontriez des collisions (si vous utilisez son abs valeur, il aura seulement2**31
valeurs).Vous avez demandé le plus court en fonction de hachage. Ce serait certainement
mais je suppose que vous n'avez pas vraiment de cette façon...
Vous pouvez faire tout de hachage vous aimez le plus court, simplement en la tronquant. md5 est toujours de 32 chiffres hexadécimaux, mais l'arbitraire d'un sous-chaîne d'elle (ou de tout autre hachage possède les qualités d'un hachage: l'égalité des valeurs de produire de l'égalité des tables de hachage, et de la dispersion des valeurs autour d'un tas.
Je suis sûr qu'il y a un CRC32 de mise en œuvre en Python, mais c'est peut-être trop court (8 chiffres hexadécimaux). Sur le plan positif, il est très rapide.
Trouvé, binascii.crc32
hash()
fonction en Python génère 2^32 trop. Ne savais pas cela, je n'ai pas vraiment utiliser Python)Si vous avez une collision, comment allez-vous dire qu'il s'est réellement passé?
Si j'étais vous, je voudrais utiliser hashlib à
sha1()
larepr()
, et puis juste obtenir un limitées substring (les 16 premiers caractères, par exemple).Sauf si vous parlez d'un grand nombre de ces objets, je suggère que vous venez d'utiliser la totalité de hachage. Puis la possibilité de collision est tellement, tellement, tellement, tellement petite, que vous ne serez jamais en direct de la voir arriver (probable).
Aussi, si vous traitez avec que de nombreux fichiers, je devine que votre technique de mise en cache doit être ajusté pour tenir compte de cela.
Nous utilisons hashlib.sha1.hexdigest(), qui produit encore plus de chaînes, pour les objets du cache avec un bon succès. Personne n'est en fait en regardant les fichiers de cache de toute façon.
Condsidering votre cas d'utilisation, si vous n'avez pas votre coeur sur l'aide de séparer les fichiers de cache et vous n'êtes pas trop loin dans cette voie de développement, vous pourriez envisager d'utiliser la
shelve
module.Cela vous donnera une persistante dictionnaire (stocké dans un seul fichier dbm) vous permet de stocker vos objets. Décapage/unpickling est effectuée de manière transparente, et vous n'avez pas à vous soucier de hachage, des collisions, des e/S de fichier, etc.
Pour la mettre en veilleuse les clés de dictionnaire, vous utilisez simplement repr(obj) et laissez
shelve
traiter accrocher vos objets pour vous. Un exemple simple:Court hachages dire que vous pouvez avoir la même valeur de hachage pour deux fichiers différents. Même chose peut se produire pour de gros hachages de trop, mais de manière plus rare.
Peut-être que ces noms de fichier devrait varier en fonction d'autres références, comme microtime (à moins que ces fichiers peuvent être créés trop vite).