IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Comment intégrer des chaines binaires dans le code source en base64


Sujet :

Python

  1. #1
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 618
    Points : 188 593
    Points
    188 593
    Par défaut Comment intégrer des chaines binaires dans le code source en base64
    On appellera ici “chaine binaire” une chaine de caractères dans laquelle chaque caractère peut avoir une valeur de 0 à 255 (bornes comprises). Intégrer une chaine binaire dans le code source n'est pas facile, parce que la chaine binaire peut comporter a priori des octets de 0 à 255, mais les caractères intégrables dans le code source, donc affichables, devraient exclure au minimum les caractères de contrôles inférieurs à 32, certains caractères comme les guillemets ou les backslashs et se limiter à des octets inférieurs 128 (c'est-à-dire rester à 7 bits) pour échapper aux problèmes d'encodages. On va utiliser ici le module base64.

    Comment intégrer des chaines binaires dans le code source en base64

    Qu'en pensez-vous ?
    Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.

    Créer des applications graphiques en Python avec PyQt5
    Créer des applications avec Qt 5.

    Pas de question d'ordre technique par MP !

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    La principale difficulté est d'automatiser la construction des scripts qui pourraient contenir ce genre de 'strings' : personne n'écrit du base64 natif!

    Ceci dit, à part l'exemple d'utilisation de base64, je ne sais pas trop quels sont les cas d'utilisation d'une telle démarche:

    - Il faut produire le script avec des outils adhoc,
    - Les fichiers sont plus gros,
    - Il faut "convertir" avant de pouvoir utiliser,

    Il est quand même plus simple d'avoir un répertoire .datafiles dans lequel stocker tous ces fichiers binaires - sans les 'intégrer' au burin dans des scripts.
    Qu'en pensez vous?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Je suis bien du même avis que vous: il vaut mieux garder des fichiers séparément.

    Cela dit, il y a un cas où c'est utile: pour des touts petits projets qui doivent être distribuables en un seul fichier et exécutables sans installation préalable.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Si on doit distribuer un seul fichier, autant livrer un exécutable construit avec un cx_freeze ou autre py2exe. Et ce faisant, on se libère aussi des dépendances sur la version de Python installée sur le système.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Bonsoir.
    il est dit dans le tuto. :
    l'Unicode ne semble pas être supporté avec Python 2.7.
    Il y a des choses intéressantes à ce sujet ici par exemple.

    Le petit exemple fonctionne sous Python 3 en faisant comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #! /usr/bin/env python3
    import base64
    ch64 = b'Ym9uam91ciDgIHRvdXMh'
    chbin = base64.b64decode(ch64)
    print(chbin)
    On travaille sur des bytes, et on obtient des bytes. C'est plus cohérent. Cela fait partie des grands changements dans Python 3, et par conséquent cela explique le comportement de Python 2.7.

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Merci rambc, ton lien est intéressant.


    Cette technique n'est pas destinée à une utilisation intensive, mais elle peut permettre ce que font les "fichiers de ressources" des bibliothèques graphiques: intégrer une icone dans le code par exemple. A noter que ces fichiers de ressource, pour Qt4 par exemple, codent en hexa ('\xFD'), ce qui multiplie par 4 l'espace pris par chaque octet, alors que base64 ne multiplie que par 1.33 environ.

    J'ai aussi utilisé base64 pour construire un identificateur unique (guid) qui contenait un chemin de disque. Cela permettait , sous Windows, de neutraliser les '\', les espaces et les caractères accentués, afin d'obtenir un identificateur syntaxiquement correct.

    On peut aussi s'en servir comme "obfuscateur" de code pour certaines parties sensibles, sinon pour cacher le code, du moins pour rendre moins faciles des modifications intempestives de l'utilisateur.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Base64 est un encodage qui n'a d'utilité que lorsqu'on utiliser une couche qui ne sait transporter proprement que des données codées sur des caractères ASCII imprimables(*) - On utilise que les 64 codes données par [A-Za-z0-9|+|/].
    (*) les premières versions de MIME servant à coder les mails par exemple, mais depuis 1994, nous avons 8BITMIME qui est moins contraignant.

    Pour ce qui est de "stocker", au moins on transforme au mieux on se portera.
    Citation Envoyé par rambc
    Il y a des choses intéressantes à ce sujet ici par exemple.
    Yes! Cela rappelle que les suites d'octets ne représentent pas toujours des chaines de caractères et qu'Unicode n'a de sens que pour un sous-ensemble de suites d'octets - pourvu qu'on sache son "encoding" pour faire automatiquement les "transformations".

    Citation Envoyé par tyrtamos
    A noter que ces fichiers de ressource, pour Qt4 par exemple, codent en hexa ('\xFD'), ce qui multiplie par 4 l'espace pris par chaque octet, alors que base64 ne multiplie que par 1.33 environ.
    Les ressources Qt4 peuvent être des fichiers binaires .PNG ou .GIF et le fichier de resources la description de leur emplacement/noms

    Citation Envoyé par tyrtamos
    J'ai aussi utilisé base64 pour construire un identificateur unique (guid) qui contenait un chemin de disque. Cela permettait , sous Windows, de neutraliser les '\', les espaces et les caractères accentués, afin d'obtenir un identificateur syntaxiquement correct.
    Pourquoi ne pas avoir utilisé Pickle dans ce cas. Ce n'est pas nécessairement plus efficace que B64 mais cela simplifie les conversions. De plus, s'il s'agit de chemins "disques", ils peuvent être représentés par une liste de paths.
    Et les fonctions d'os.path permettent de les manipuler sans trop se soucier de l'environnement Windows, Linux, OSX, ... pour peu qu'on traite proprement la racine.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour wiztricks,

    Citation Envoyé par wiztricks Voir le message
    Pourquoi ne pas avoir utilisé Pickle dans ce cas. Ce n'est pas nécessairement plus efficace que B64 mais cela simplifie les conversions. De plus, s'il s'agit de chemins "disques", ils peuvent être représentés par une liste de paths.
    Et les fonctions d'os.path permettent de les manipuler sans trop se soucier de l'environnement Windows, Linux, OSX, ... pour peu qu'on traite proprement la racine.

    Et pourquoi pas base64?

    Exemple: je veux un identificateur composé uniquement d'ascii imprimables sans espace, et qui soit construit à partir d'un chemin (ici en utf-8). Cet identificateur est construit pendant l'exécution d'un programme qui est 'multiplateforme'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    print base64.b64encode(r"C:\Users\tyrtamos\Documents\Mes sources de données")
    QzpcVXNlcnNcdHlydGFtb3NcRG9jdW1lbnRzXE1lcyBzb3VyY2VzIGRlIGRvbm7DqWVz
    C'est difficile de faire plus simple, et, sauf à être définitivement fâché avec base64 (?), je ne vois pas l'intérêt de chercher autre chose.


    Tu pourrais me dire comment on pourrait faire la même chose avec Pickle? et avec les autres solutions de ta remarque (liste de path, ...)?

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut Tyrtamos,

    Exemple: je veux un identificateur composé uniquement d'ascii imprimables sans espace, et qui soit construit à partir d'un chemin (ici en utf-8).
    La première question est pourquoi "ASCII, imprimables dans espaces?"
    C'est une contrainte pouvant être imposée par le transfert de données via des modems 'antiques'.
    Je ne vois pas comment, de nos jours, le programmeur Python lambda peut rencontrer cela.

    Cet identificateur est construit pendant l'exécution d'un programme qui est 'multiplateforme'.
    J'entends que le programme soit multi-plateforme par "se comporte de la même façon" en "laissant aux bibliothèques Python la gestion des parties spécifiques".
    Une implication est qu'on ne peut pas mettre dans les scripts de littéraux de la forme: "C:\Users\tyrtamos\Documents\Mes sources de données"
    car c'est un path windows!

    Mais là je ne comprends plus la relation avec base64.
    Nous avons ici une chaine de caractère (pas une suite d'octets arbitraires) sérialisable en utf-8. Pourquoi faire plus compliqué?

    Tu pourrais me dire comment on pourrait faire la même chose avec Pickle? et avec les autres solutions de ta remarque (liste de path, ...)?
    Pour l'instant, si le but est de sérialiser de l'Unicode représentant des caractères latins, utf-8 devrait suffire....
    Mais n'étant pas certain d'avoir compris "le but", çà attendra un peu.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour wiztricks,

    J'ai de bonnes raisons de vouloir un identificateur comme cela. Et c'est pour un programme en PyQt4 de 10000 lignes de code en multiplateforme avec base SQL, qui fonctionne très bien . Je note que tu n'as pas de solution concrète à mon problème, à part de le remettre en cause.

    Je me suis contenté ici de témoigner de l'intérêt que je portais à base64, pour résoudre, entre autres, ce problème précis. En ce qui me concerne, j'ai résolu mon problème et ça me suffit.

    Le reste ne m'intéresse pas beaucoup...

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    J'ai de bonnes raisons de vouloir un identificateur comme cela. Et c'est pour un programme en PyQt4 de 10000 lignes de code en multiplateforme avec base SQL, qui fonctionne très bien. Je note que tu n'as pas de solution concrète à mon problème, à part de le remettre en cause.
    Mon propos n'est pas remettre en cause un choix fait "pour de bonnes raisons".
    Juste essayer de comprendre le pourquoi du choix... conduisant à sérialiser en base64: c'est pas interdit, çà fonctionne,... Mais c'est quand même pas banal!

    Et sans information, pas de solution.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Juste essayer de comprendre le pourquoi du choix... conduisant à sérialiser en base64: c'est pas interdit, çà fonctionne,... Mais c'est quand même pas banal!
    Mon problème et sa solution se trouve dans le dernier message du fil: http://www.developpez.net/forums/d10...ion-programme/.

    Il s'agit d'un logiciel pour des concours photos dans un photo-club.

    Le programme a au départ un identifiant unique (guid) de 40 caractères ascii imprimable (hors espace et certains autres caractères). On donne en argument au lancement du programme, le répertoire des données sur lequel il doit travailler. On ajoute à cet identifiant le chemin des données (répertoire qui peut contenir une base sqlite3 par exemple) encodé base64, et on se sert de l'identifiant résultant pour empêcher qu'on lance 2 fois le même programme sur les mêmes données, grâce à la technique du "sharedMemory". Mais on permet, tant sur Windows que sur Linux, de lancer plusieurs fois ce même programme, tant qu'ils travaillent sur des données différentes. On peut ainsi sur le même PC et avec le même programme, suivre, sans risque de conflit de données, plusieurs concours en même temps.

    Pour d'autres applications, on pourrait tout aussi bien empêcher qu'un même utilisateur lance 2 fois le même programme (pour une raison quelconque), tout en permettant à un autre utilisateur d'utiliser, lui aussi et en même temps, le même programme. On prend alors comme complément d'identificateur le répertoire utilisateur encodé base64, répertoire qu'il est facile de retrouver avec Python.

    Je sais que la solution du "sharedMemory" est discutée, mais aucune autre solution qu'on m'a suggérée ne fonctionne en répondant à tous les critères, tout en restant aussi simple. Et manifestement, ça marche très bien (WinXP, Vista, Win7, Ubuntu10.10).

    Quand à base64, je me suis contenté de chercher un moyen simple de transformer un chemin disque en chaine qui n'a plus ni espace, ni '\', ni caractère accentués, etc... bref, qui soit syntaxiquement accepté comme identificateur par le système. D'autres solutions qui feraient la même chose tout en étant aussi simples, auraient aussi mon agrément.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  13. #13
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Si je puis me permettre d'ajouter mon grain de sel sous forme d'un bout de code, voici un "truc" que j'ai utilisé pour un script qui devait s'autodéployer et être livré sous forme d'un fichier unique : base64 + zip.
    Ca donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    def deflate_base64_zip ( base64zip , path ):
        # Décompresse le contenu d'un fichier zip dans le répertoire path (qui doit exister).
        # Le fichier zip est contenu dans base64zip encodé en base 64.
        import zipfile
        import base64
        cwd = os.getcwd()
        os.chdir( path )
        # créé un fichier qui contient la chaîne base64zip convertie en binaire
        fic = open('deflate_base64_zip.zip','wb')
        fic.write( base64.b64decode( base64zip ))
        fic.close()
        # extrait tout le contenu du zip sur place (avec les sous dossiers)
        zip = zipfile.ZipFile('deflate_base64_zip.zip','r')
        zip.extractall()
        zip.close()
        os.remove('deflate_base64_zip.zip')
        os.chdir( cwd )
     
    # fichier machin zippé et base64-isé :
    machin_zip = "UEsDBAoAkccaY+ ... LnN3ZkNXUwhjE"
     
    # déploiement du fichier machin
    deflate_base64_zip( machin_zip,'c:\spam' )
    Voilà... si ça peut rendre service...

    Hadrien
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut Tyrtamos,

    Citation Envoyé par tyrtamos Voir le message
    Mon problème et sa solution se trouve dans le dernier message du fil: http://www.developpez.net/forums/d10...ion-programme/.
    Pardon pour le silence, j'étais occupé "ailleurs".
    Je suppose que le passage par base64 est nécessaire, dans ce cas, pour construire un identifiant accepté par QtCore.QSharedMemory.

    Pour faire la même chose sans passer par Qt (et base64), on peut utiliser un vieux truc Python/PERL qui s'appelle portalocker

    En gros le principe est le même: une seule instance de l'application ne peut travailler dans un répertoire dit de travail.
    Si c'est un répertoire de travail, on peut supposer qu'elle peut y créer des fichiers ou lire un fichier existant qui sera le nom du "verrou".
    Puis on essaie de verrouiller le fichier avec la primitive qui va bien en fonction de l'OS ce qui donne un cas Windows et un cas pour le reste du monde.

    Et puis voilà.
    Notes:
    • Dans tous ces exemples, on compte sur l'OS pour faire libérer le verrou. Parfois, il peut mettre un certain temps (petit) pour faire le ménage... On pourrait écrire un exit handler (atexit) pour aider un peu...
    • La fonction de base "marche" mais on ne sait pas qui verrouille le fichier et à fortiori pouvoir dégager le récalcitrant.


    Reste le cas général pour l'ensemble de primitives systèmes qui demandent la création d'un identifiant "unique" tarabiscoté. Base64 peut être une solution... mais... elle n'est pas "secure".
    Note: Un parano pourra dire que qu'on peut saboter le fonctionnement de l'application à partir du nom externe. Les UNIX permettent de créer des identifiants en fonction du nom du fichier (et des droits d'accès) mais leur unicité n'est pas garantie (voir le man de ftok).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Pour générer un identifiant unique à partir d'un path (ou d'une chaîne quelconque), j'utiliserais hashlib:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> import hashlib
    >>> hashlib.sha1("/home/toto/tata").hexdigest()
    '95b5dee73512287c73f9543648206e92adbebc9d'
    Le risque de collision est négligeable, et la longueur de l'identifiant est fixe.

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par dividee Voir le message
    Pour générer un identifiant unique à partir d'un path (ou d'une chaîne quelconque), j'utiliserais hashlib:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> import hashlib
    >>> hashlib.sha1("/home/toto/tata").hexdigest()
    '95b5dee73512287c73f9543648206e92adbebc9d'
    Le risque de collision est négligeable, et la longueur de l'identifiant est fixe.
    Certes mais çà ne traite pas les éventuels soucis de sécurité: il suffit de connaître la chaîne de caractères pour générer la séquence...
    portalocker demande l'ouverture d'un fichier et donc offre la possibilité de poser des droits d'accès dessus.
    Cela relève de détails, mais je ne sais pas trop ce qui peut être utilisé avec les bibliothèques Python de base qui permettraient de faire cela de façon "portable" sans se reposer sur les "fichiers" (ou plutôt des mécaniques qu'on hérite grâce à...)
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  17. #17
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Merci pour ces idées complémentaires.

    Celle qui me séduit le plus est le hashlib.sha1, grâce à la limite de la longueur de la chaine, en plus de sa simplicité. Je pense aussi que les risques de collision négligeables dans mon cas. De plus, je n'ai pas besoin de fonction inverse.

    En reprenant mon exemple plus haut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    import hashlib
    print hashlib.sha1(r"C:\Users\tyrtamos\Documents\Mes sources de données").hexdigest().upper()
    812F8B81C54DE7B2E9535327E3B9B6226E7125B2
    Alors que le même répertoire aurait donné une chaine de 68 caractères avec base64.

    Ainsi, avec par exemple un identificateur de 40 caractères calculé comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    from random import randint
    rand2hex = lambda n: ''.join([hex(randint(0,255))[2:].upper().zfill(2) for i in xrange(0,n)])
    print rand2hex(20)
    F9CD63CE9C33354851CA2B00AB02227062ED1FBF
    Je peux construire, comme je le souhaitais, cet identifiant unique (ici de 80 caractères) pour le programme, travaillant sur un répertoire de données.

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  18. #18
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par tyrtamos
    Celle qui me séduit le plus est le hashlib.sha1, grâce à la limite de la longueur de la chaine, en plus de sa simplicité. Je pense aussi que les risques de collision négligeables dans mon cas. De plus, je n'ai pas besoin de fonction inverse.
    Comme on chiffre des chaînes de longueur variables généralement plus grandes que 64 bytes, les risques de collisions sont faibles mais pas nuls.
    Le jour ou cela se produira le bonhomme qui devra trouver "le pourquoi" sera bien embêté pour en trouver la cause.
    L'identité des processus qui verrouillent la section n'est pas assurée, il pourra se laisser aller à toutes conjectures paranos.

    Mais pourquoi faire simple (genre portalocker) si on peut faire compliqué?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  19. #19
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Mais pourquoi faire simple (genre portalocker) si on peut faire compliqué?
    Désolé, wiztricks, mais avant mon précédent message, j'ai regardé portalocker, et... je n'ai rien compris: 119 lignes de code avec quelques phrases en anglais ne me suffisent pas: pourrais-tu développer un peu et donner un exemple?

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  20. #20
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Il n'y a rien dans ce code juste des déclarations pour rendre "portable" la suite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    # ouverture du fichier "clé"
    f = open(f, 'r+')
    try:
        os_lock(f)
    except:
        raise Exception('pas de bol, c'est occupé')
    else:
        # j'ai le verrou, je fais ce que je veux.
    Le code délire un peu pour définir os_lock. En fait, c'est une modif d'un truc de 2001 qui a juste été retouché pour remplacer win32com par msvcrtl (inclue dans Python).
    S'il ne s'embêtaient pas à définir les symboles qui sont (aujourd'hui) définis dans les modules... et imaginer que le fichier pourrait être autre que vide, cela pourrait être réduit - peut être un peu trop -, çà donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    __all__ = [ 'os_lock' ]
     
    # ce qu'on fait dans le cas UNIX, OSX, Linux...
    def get_ux_lock():
        from fcntl import lockf, LOCK_NB, LOCK_EX
        def os_lock(file, range=80):
            return lockf(file.fileno(),  LOCK_EX | LOCK_NB, range, 1)
        return os_lock
     
    # ce qu'on fait dans le cas Windows
    def get_w32_lock():
        from msvcrt import locking, LK_NBLCK, LK_UNLCK
        def os_lock(file, range=80):
            return locking(file.fileno(),  LK_NBLCK, range) 
        return os_lock
     
    # une facon comme une autre de s'assurer que les bons modules sont la
    # plutot que de tester sys.platform... le tout ne servant qu'à definir os_lock
    # dans global avec la definition qui va bien.
    try:
        import fcntl
    except:
        pass
    else:
        os_lock = get_ux_lock()
     
    if 'os_lock' not in globals():
        try:
            import msvcrt
        except:
            pass
        else:
            os_lock = get_w32_lock()
     
    # dans le cas ou ce n'est pas si portable...
    assert 'os_lock' in globals(), 'unable to define os_lock routine'
     
    # quand je suis ici, j'ai ce qu'il faut dans os_lock...
    # le suite ne fait que "tester"
    # pour faire planter, yaka lancer python ailleurs et faire:
    # >>> from portalocker import os_lock
    # >>> f = open('test.lock', 'r+')
    # >>> os_lock(f)
    # avant de lancer ce qui suit...
    if __name__ == '__main__':
        import os
        fname = 'test.lock'
     
        if not os.path.exists(fname):
            open(fname, 'w').close()
     
        myLock = open(fname, 'r+')
        os_lock(myLock)
        print 'Bye'
    Note: J'ai écris cela à la volée avec un petit test windows, pardon pour les autres bugs.
    Après, on peut bien sûr broder:
    - créer os_unlock et l'appeler via atexit
    - s'assurer que l'exception est bien celle attendue
    - remonter un boolean sauf dans les cas imprévus - les exceptions pour le business de la fonction, pas glop.
    - ajouter une logique de timeout,
    -...
    Mais le principe est "simple": un fichier auquel on a ou pas le droit d'accès qui sert à verrouiller le répertoire de travail pour une seule instance de l'application. Le répertoire est "unique" (os.abspath()), et il s'écrit comme il veut Windows, Unix,.... on s'en fout...
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 14
    Dernier message: 16/04/2013, 12h22
  2. Réponses: 2
    Dernier message: 31/03/2006, 16h48
  3. Réponses: 11
    Dernier message: 13/03/2006, 17h51
  4. Comment utiliser des instructions SSE2 dans un code c++?
    Par alexIsBack dans le forum x86 32-bits / 64-bits
    Réponses: 7
    Dernier message: 22/02/2006, 19h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo