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 obtenir la représentation hexadecimale d'une chaine de caractères


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut Comment obtenir la représentation hexadecimale d'une chaine de caractères
    Comment obtenir la représentation hexadecimale d'une chaine de caractères

    Bonjour,

    Je cherche l'équivalent de la fonction php unpack:
    unpack('H*', 'AIJKZ') => string(10) "41494a4b5a"

    hex(ord('A')) + hex(ord('I')) + hex(ord('J')) + hex(ord('K')) + hex(ord('Z')) retourne '0x410x490x4a0x4b0x5a",
    ce qui n'est pas tout à fait la même chose.

    Merci.

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 052
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 052
    Par défaut
    C'est vrai que c'est une notation assez spéciale

    J'ai créé une fonction hexa pour ton cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def hexa(nb):
    	res=[]
    	for i in nb: res.append(hex(ord(i)).strip('0x'))
    	print ''.join(res)
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    hexa=lambda nb:''.join([hex(ord(i)).strip('0x') for i in nb])
    Résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> hexa('AIKZTYUI')
    41494b5a54595549

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,
    Juste pour le fun:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> hexs=lambda s: ''.join(map(lambda c: '%02x' % ord(c), s))
    >>> hexs('xyz')
    '79787a'
    >>>
    - W
    PS: "map" applique une fonction sur les items d'un iterable, ici un string.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    C'est vrai que c'est une notation assez spéciale
    rien de spécial, c'est pour mettre à plat du packed-décimal.

    la fonction hexs est juste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> hexs=lambda s: ''.join(map(lambda c: '%02x' % ord(c), s))
    >>> hexs('abc\ndef')
    '6162630a646566'
    >>>
    la fonction hexa est fausse, elle supprime le quartet de gauche quand il est égal à zéro.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> hexa=lambda nb:''.join([hex(ord(i)).strip('0x') for i in nb])
    >>> hexa('abc\ndef')
    '616263a646566'
    >>>
    il faut la modifier comme ci-dessous ".rjust(2, '0')"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> hexa=lambda nb:''.join([hex(ord(i)).strip('0x').rjust(2, '0') for i in nb])
    >>> hexa('abc\ndef')
    '6162630a646566'
    >>>
    j'ai trouvé des choses plus sophistiquées :
    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
    def comp3(nb):
    	cumul = 0
    	for c in nb[:-1]:
    		i = ord(c)  
    		gauche = (i & 0xf0) >> 4      #    quartet gauche (fort)
    		droit = i & 0x0f              #    quartet droit (faible)
    		cumul = cumul * 10 + gauche   #    on cumule
    		cumul = cumul * 10 + droit 
     
    	i = ord(nb[-1])  
    	gauche = (i & 0xf0) >> 4      	  #    quartet gauche (unité)
    	sign = i & 0x0f	                  #	   le signe	
    	cumul = cumul * 10 + gauche       #    on cumule
     
    	if sign in (0x0b, 0x0d ):
    		return '-' + str(cumul)
    	else:
    		return '+' + str(cumul)
     
    def comp3B(nb):
    	cumul = ''
    	for c in nb[:-1]:
    		i = ord(c)  
    		gauche = (i & 0xf0) >> 4      		#    quartet gauche (fort)
    		droit = i & 0x0f              		#    quartet droit (faible)
    		cumul += str(gauche) + str(droit)	#    on cumule
     
    	i = ord(nb[-1])  
    	gauche = (i & 0xf0) >> 4      	 		#    quartet gauche (unité)
    	sign = i & 0x0f	                   		#    le signe	
    	if sign in (0x0b, 0x0d ):
    		return '-' + cumul + str(gauche)
    	else:
    		return '+' + cumul + str(gauche)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> comp3(chr(0x29) + chr(0x00) + chr(0x3d))
    '-29003'
    >>> comp3(chr(0x29) + chr(0x00) + chr(0x3f))
    '+29003'
    >>>
    reste à voir les temps de réponse.

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,
    bibliothèque que je n'ai pas trouvée tantôt mais qui est applicable ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> import binascii
    >>> binascii.hexlify('abcdght')
    '61626364676874'
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Bravo wiztricks,

    c'est exactement ce que je cherchais.
    conversion d'un fichier de 4Mo en entrée (8 en sortie)

    binascii.hexlify : 0,04 sec
    unpack php : 0,07 sec
    lambda hexs : 4,10 sec

    merci

  7. #7
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 052
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 052
    Par défaut
    Salut,
    bibliothèque que je n'ai pas trouvée tantôt mais qui est applicable ici:
    Oh oui je ne connaissais pas celle la,

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,

    La performance en Python n'a pas le même sens qu'ailleurs!
    Vous avez la performance du "codeur" au sens, traduire un besoin en quelques lignes de code (en général "une").
    C'est une approche RAD, elle permet de voir si çà le fait...

    Et la recherche de performance pour un traitement particulier...
    Dans ce cas, Python étant interprété, l'approche RAD est toujours sous optimale... La où Python devient "magique", c'est qu'il est à utiliser comme langage d'intégration: s'il existe une bibliothèque C 'intéressante', il n'est pas difficile de l'intégrer au langage via des bibliothèques.
    Exemple: QT, libxml, wxWorks,...

    Si vous ne dites pas "je voudrais convertir de gros fichiers", nous avons un penchant naturel à écrire la ligne de code qui tue mais pas nécessairement "performante".

    Essayez voir:
    The binhex module defines the following functions:
    binhex.binhex(input, output)¶
    Convert a binary file with filename input to binhex file output. The output parameter can either be a filename or a file-like object (any object supporting a write() and close() method).
    Ca ne devrait pas aller "significativement" plus vite que binascii, mais RAD dit que moins de lignes de code à écrire c'est toujours çà de pris.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    binhex.binhex ne convient pas, car il y a d'autres traitement à effectuer.

    Le but du jeu est de remplacer le programme VB6 qui tourne tous les jours depuis une dizaine d'années par un script python ou php.

    Il y a 256 fichiers correspondant à autant de tables.
    La plus grosse table contient 1 200 000 enregistrements de 25 champs.
    Les fichiers d'entrée font un total de 500 Mo , ceux en sorties 1Go.

    La version php, pourtant très optimisée, est 6 à 7 fois moins rapide que le VB.

    Mes premiers tests avec python sont encourageants, surtout avec le binascii.hexlify.
    Si j'arrive à obtenir un traitement 2 à 3 fois moins rapide, ça conviendra parfaitement.

    Sinon, je me mettrai au C.

    A+

  10. #10
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,
    J'espère que vous parallélisez un peu les traitements.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Bonsoir,

    j'ai effectué les tests de vitesse aujourd'hui.

    Résultat des courses :
    VB6: 3 secondes, python (code ci-dessous): 6 secondes, php: 18 secondes.

    le vb6 compilé, contient égalemnt des call directs à certaines api windows.
    je vais utiliser python car l'augmentation de durée, 6 à 7 minutes par nuit, est supportable.
    Ce n'est pas jouable avec php, 35 à 40 minutes d'augmentation.

    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    #!/usr/bin/env python
    # -*- coding:UTF-8 -*-
    """ conversion de la table ACT """
     
    from time import time
    import binascii
     
    def trt_act():
    	""" création du fichier étendu 200 000 records, 20 Mo """
     
    	i = 0
    	inFile = open('packed_file', 'r')
    	outFile = open('mis_a_plat', 'w')
     
    	while 1:
    		inChr = inFile.read(47)
    		if inChr == '' : 		break
    		inHex = binascii.hexlify(inChr)
     
    		out = ''
    		out += trt_pack(inHex[0:6])			#iavo
    		out += "$"
    		out += trt_date(inHex[6:15])		#dins
    		out += "$"
    		out += inChr[8:9]					#cins
    		out += "$"
    		out += trt_date(inHex[18:27])		#dces
    		out += "$"
    		out += inChr[14:15]					#cces
    		out += "$"
    		out += trt_pack(inHex[30:34]) 		#iban
    		out += "$"
    		out += inChr[17:20]					#natv
    		out += "$"
    		out += inChr[20:21]					#catv
    		out += "$"
    		out += trt_pack(inHex[42:48]) 		#istr
    		out += "$"
    		out += trt_pack(inHex[48:52]) 		#qann
    		out += "$"
    		out += trt_pack(inHex[52:56])		#qmoi
    		out += "$"
    		out += trt_pack(inHex[56:60]) 		#qjou
    		out += "$"
    		out += trt_pack(inHex[60:66])		#cpay
    		out += "$"
    		out += trt_packdec(inHex[66:74], 4)	#qexe
    		out += "$"
    		out += trt_packdec(inHex[74:82], 2)	#qex2
    		out += "$"
    		out += inChr[41:42]					#ccer
    		out += "$"
    		out += trt_date(inHex[84:93])		#dmaj
    		outFile.write(out + '\n')
     
    	inFile.close(), outFile.close();
     
    def trt_pack(s):
    	""" traitement des entiers """
    	if s[-1] == 'f' : 			
    		return '+' + s[:-1]
    	elif s[-1] == 'd'  :	
    		return '-' + s[:-1]
    	else :
    		return '%' + s[:-1]	
     
    def trt_packdec(s, d):
    	""" traitement des nombres décimaux """
     
    	if s[-1] == 'f' : 			
    		sign = '+'
    	elif [-1] == 'd'  :	
    		sign = '-'
    	else :
    		sign = '%'
    	return sign + s[:len(s)-d-1] + ',' + s[len(s)-d-1:-1]
     
    def trt_date(d):
    	""" traitement des dates """
     
    	aaaa = d[1:5]
    	mm = d[5:7]
    	jj = d[7:]
     
    	if aaaa == '0000' : 			
    		return ''.ljust(10, ' ')
    	elif mm == '00' or jj == '00' :	
    		return '01/01/' + aaaa
    	else :
    		return jj + '/' + mm + '/' + aaaa	
     
    def create_act():
    	""" création du fichier de test 200 000 records, 9 Mo """
     
    	z = chr(0x00) + chr(0x00) + chr(0x1f) 	 						#iavo
    	z += chr(0x01) + chr(0x94) + chr(0x60) + chr(0x41)  + chr(0x2f)	#dins 			      				
    	z += 'S'														#cins
    	z += chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00)  + chr(0x0f)	#dces 			      				
    	z += ' '														#cces
    	z += chr(0x10) + chr(0x5f)	 									#iban
    	z += '511'														#natv
    	z += '5'														#catv
    	z += chr(0x29) + chr(0x00) + chr(0x3f)	 						#istr
    	z += chr(0x03) + chr(0x8f)										#qann
    	z += chr(0x02) + chr(0x6f)										#qmoi
    	z += chr(0x01) + chr(0x2f)										#qjou
    	z += chr(0x10) + chr(0x23) + chr(0x1f) 							#fill
    	z += chr(0x03) + chr(0x82) + chr(0x61) + chr(0x2f)				#qexe
    	z += chr(0x03) + chr(0x72) + chr(0x61) + chr(0x2f)				#qex2
    	z += 'C'														#ccer
    	z += chr(0x02) + chr(0x00) + chr(0x31) + chr(0x22)  + chr(0x5f)	#dmaj 			      				
     
    	i = 0
    	outFile = open('packed_file', 'w')
    	while i < 200000:
    		outFile.write(z)
    		i += 1
     
    	lg = len(z)
    	print lg
    	outFile.close()
     
    #=============
    if __name__ == "__main__":
    	import os 
    	os.system('clear')
    	t = t1 = time()
    	create_act()
    	print 'create: ' + str(time() - t1)
    	t1 = time()
    	trt_act()
    	print 'unpack: ' + str(time() - t1)
    	print 'ghgh' + 'éèàù'

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 106
    Par défaut
    Je te propose ceci si tu veux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    >>> a="message"
    >>> "0x"+a.encode("hex")
    '0x6d657373616765'
    >>> a.encode("hex")
    '6d657373616765'
    >>>

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Merci,

    avec binascii.hexlify les résultats sont justes et les temps de réponse satisfaisants.

    je ferai un test avec encode dès que je pourrai.

    A quoi cela sert-il ?

    C'est pour faire la mise à plat de fichiers qui viennent d'une base de données sur un mainframe.
    Les fichiers mis à plat sont chargés dans un DB2/windows pour de l'infocentre et des mailings très personnalisés.

    Il y a du 'packed-decimal', du binary, et une table de translation EBCDIC/ASCII pour certains caractères.

    toutes les nuits 1,5 Go traités, 250 tables, 5 millions d'enregistrements.
    3 heures de transfert FTP,
    6 minutes de conversion,
    30 minutes de chargement dans DB2.

    Je profite du changement de serveur pour basculer les traitements VB98 vers python et PHP.
    A+

  14. #14
    Membre émérite
    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
    Par défaut
    Citation Envoyé par avi3000 Voir le message
    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
     
    		out = ''
    		out += trt_pack(inHex[0:6])			#iavo
    		out += "$"
    		out += trt_date(inHex[6:15])		#dins
    		out += "$"
    		out += inChr[8:9]					#cins
    		out += "$"
    		out += trt_date(inHex[18:27])		#dces
    		out += "$"
    		out += inChr[14:15]					#cces
    		out += "$"
    		out += trt_pack(inHex[30:34]) 		#iban
    		out += "$"
    		out += inChr[17:20]					#natv
    		out += "$"
    		out += inChr[20:21]					#catv
    		out += "$"
    		out += trt_pack(inHex[42:48]) 		#istr
    		out += "$"
    		out += trt_pack(inHex[48:52]) 		#qann
    		out += "$"
    		out += trt_pack(inHex[52:56])		#qmoi
    		out += "$"
    		out += trt_pack(inHex[56:60]) 		#qjou
    		out += "$"
    		out += trt_pack(inHex[60:66])		#cpay
    		out += "$"
    		out += trt_packdec(inHex[66:74], 4)	#qexe
    		out += "$"
    		out += trt_packdec(inHex[74:82], 2)	#qex2
    		out += "$"
    		out += inChr[41:42]					#ccer
    		out += "$"
    		out += trt_date(inHex[84:93])		#dmaj
    Avec autant de concaténations, pas étonnant que ça prenne beaucoup de temps.

    Essayez trois choses:
    1. Écrire directement dans outfile. Après tout, la stdlib tient des buffers pour ce genre de cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    write = outfile.write
    write(trt_pack(inHex[0:6]))
    write("$")
    ...
    2. Utilisez un StringIO (from cStringIO*import StringIO)
    3. Utilisez un ctypes.c_buffer.

    En plus de cela, je ne suis pas convaincu que ce soit efficace de prendre un gros morceau de données, puis toutes des tranches:
    C'est des appels de méthodes et des copies en mémoire pour pas grand chose. Il y a surement une autre solution.

    Pour finir, selon votre version de Python, vous pourriez utiliser Psyco.

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Citation Envoyé par jack_x4 Voir le message
    Je te propose ceci si tu veux : a.encode("hex")
    Bonjour,
    ça fonctionne, les résultats sont justes.
    Seul bémol, c'est 2 fois moins rapide que binascii.hexlify.

    tests ci-dessous.
    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
    #!/usr/bin/env python
    # -*- coding:UTF-8 -*-
    """  test encode/hexlify  """
     
    from time import time
    import binascii
     
    def trt():
        inChr = 'oper' * 10
        t1 = time()
        i = j = 1000000
        while i > 0 :
            inHex = inChr.encode("hex")
            i -= 1
     
        print 'encode: ' + str(time() - t1)
     
        t1 = time()
        i = j
        while i > 0 :
            inHex = binascii.hexlify(inChr)
            i -= 1
     
        print 'hexlify: ' + str(time() - t1)
     
        inChr = 'oper' * 13
        t1 = time()
        i = j
        while i > 0 :
            inHex = inChr.encode("hex")
            i -= 1
     
        print 'encode: ' + str(time() - t1)
     
        t1 = time()
        i = j
        while i > 0 :
            inHex = binascii.hexlify(inChr)
            i -= 1
     
        print 'hexlify: ' + str(time() - t1)
     
    if __name__ == "__main__" :
        t1 = time()
        trt()
        print 'total: ' + str(time() - t1)

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Essayez trois choses:
    1. Écrire directement dans outfile. Après tout, la stdlib tient des buffers pour ce genre de cas.
    2. Utilisez un StringIO (from cStringIO*import StringIO)
    3. Utilisez un ctypes.c_buffer.
    Bonjour,

    1.Faux: Il est plus rapide de travailler en mémoire et d'écrire les fichiers par bloc. Une simple concaténation est plus rapide qu'un appel de routine système d'entrée-sortie. De Cobol à Python, en passant par PHP et VB, tous les langages que je connais fonctionne ainsi. En cas de doute, un test.

    2.Faux: j'ai testé, pas bien. 8,5 secondes contre 6 secondes avec la concaténation.

    3.Presque bon: Gain de temps marginal (1 à 2%). mais l'écriture du programme est beaucoup plus lourde, voir le code ci-dessous.
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    from ctypes import *
     
    class OUTSTRUC(Structure):
    	_fields_ = [("iavo", c_char * 6),  ("iavo_f", c_char),
    				("dins", c_char * 10), ("dins_f", c_char),
    				("cins", c_char),	   ("cins_f", c_char),
    				("dces", c_char * 10), ("dces_f", c_char),
    				("cces", c_char), 	   ("cces_f", c_char),
    				("iban", c_char * 4),  ("iban_f", c_char),
    				("natv", c_char * 3),  ("natv_f", c_char),
    				("catv", c_char),      ("catv_f", c_char),
    				("istr", c_char * 6),  ("istr_f", c_char),
    				("qann", c_char * 4),  ("qann_f", c_char),
    				("qmoi", c_char * 4),  ("qmoi_f", c_char),
    				("qjou", c_char * 4),  ("qjou_f", c_char),
    				("cpay", c_char * 6),  ("cpay_f", c_char),
    				("qexe", c_char * 9),  ("qexe_f", c_char),
    				("qex2", c_char * 9),  ("qex2_f", c_char),
    				("ccer", c_char),      ("ccer_f", c_char),
    				("dmaj", c_char * 10), ("dmaj_f", c_char)]
     
    def trt_act_ctypes(lg):
    	""" création du fichier étendu 200 000 records, 20 Mo """
     
    	i = nbrec = 0
    	inFile = open('packed_file', 'r')
    	outFile = open('ctypes_a_plat', 'wb')
    	outBuf = OUTSTRUC()
    	outBuf.iavo_f = '$' 
    	outBuf.dins_f = '$' 
    	outBuf.cins_f = '$' 
    	outBuf.dces_f = '$' 
    	outBuf.cces_f = '$' 
    	outBuf.iban_f = '$' 
    	outBuf.natv_f = '$' 
    	outBuf.catv_f = '$' 
    	outBuf.istr_f = '$' 
    	outBuf.qann_f = '$' 
    	outBuf.qmoi_f = '$' 
    	outBuf.qjou_f = '$' 
    	outBuf.cpay_f = '$' 
    	outBuf.qexe_f = '$' 
    	outBuf.qex2_f = '$' 
    	outBuf.ccer_f = '$' 
    	outBuf.dmaj_f = '\n' 
     
     
    	while 1:
    		inChr = inFile.read(lg)
    		if inChr == '' : 		break
    		inHex = binascii.hexlify(inChr)
    		nbrec += 1
     
    		outBuf.iavo     = trt_pack(inHex[0:6])			#iavo
    		outBuf.dins     = trt_date(inHex[6:15])			#dins
    		outBuf.cins  	= inChr[8:9]					#cins
    		outBuf.dces  	= trt_date(inHex[18:27])		#dces
    		outBuf.cces  	= inChr[14:15]					#cces
    		outBuf.iban  	= trt_pack(inHex[30:34])		#iban
    		outBuf.natv  	= inChr[17:20]					#natv
    		outBuf.catv  	= inChr[20:21]					#catv
    		outBuf.istr  	= trt_pack(inHex[42:48]) 		#istr
    		outBuf.qann     = trt_pack(inHex[48:52]) 		#qann
    		outBuf.qmoi  	= trt_pack(inHex[52:56])		#qmoi
    		outBuf.qjou  	= trt_pack(inHex[56:60]) 		#qjou
    		outBuf.cpay  	= trt_pack(inHex[60:66])		#cpay
    		outBuf.qexe  	= trt_packdec(inHex[66:74], 4)	#qexe
    		outBuf.qex2  	= trt_packdec(inHex[74:82], 2)	#qex2
    		outBuf.ccer  	= inChr[41:42]					#ccer
    		outBuf.dmaj  	= trt_date(inHex[84:93])		#dmaj
    		outFile.write(outBuf)
     
    	inFile.close(), outFile.close()

  17. #17
    Membre émérite
    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
    Par défaut
    Citation Envoyé par avi3000 Voir le message
    Une simple concaténation est plus rapide qu'un appel de routine système d'entrée-sortie.
    Ai-je jamais prétendu le contraire ?

    Citation Envoyé par Antoine_935
    Après tout, la stdlib tient des buffers pour ce genre de cas
    La stdlib s'exécute dans l'espace utilisateur (user space), et non dans le système (kernel space). Pas d'appel système donc, mais un appel à une méthode C que les gens travaillent à optimiser depuis bien 30 ans maintenant.


    Et oui, j'en suis sur.

    2.Faux: j'ai testé, pas bien. 8,5 secondes contre 6 secondes avec la concaténation.
    Pourrais-je voir le code en question ? Vous avez du rater un élément.

    3.Presque bon: Gain de temps marginal (1 à 2%). mais l'écriture du programme est beaucoup plus lourde, voir le code ci-dessous.
    Je parlais d'un buffer, pas d'une structure. Après, si vous préférez la méthode rude, c'est votre souci.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    test du stringIO
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    #!/usr/bin/env python
    # -*- coding:UTF-8 -*-
    """ Conversion de act  """
     
    from time import time
    import binascii
    from ctypes import *
     
    #================================
    def trt_concat():
        """   traitement act """
     
        i = 0
        inFile = open("{0}/{1}.bin".format('D:/py', 'act'), 'r')
        outFile = open("{0}/{1}.2.ans".format('D:/py', 'act'), 'w')
        while 1:
            inChr = inFile.read(47)
            if inChr == '' : 		break
            inHex = binascii.hexlify(inChr)
     
            out = ''
            out += trt_pack(inHex[  0:  6])	        #matricule
            out += '$'
            out += trt_date(inHex[  6: 15])	        #dins
            out += '$'
            out += inChr[  8:  9]					#cins
            out += '$'
            out += trt_date(inHex[ 18: 27])	        #dces
            out += '$'
            out += inChr[ 14: 15]					#cces
            out += '$'
            out += inChr[ 15: 16]					#natv
            out += inChr[ 16: 17]
            out += inChr[ 17: 18]
            out += '$'
            out += inChr[ 18: 19]					#catv
            out += '$'
            out += trt_pack(inHex[ 38: 42])	        #ibar
            out += '$'
            out += trt_pack(inHex[ 42: 48])	        #istr
            out += '$'
            out += trt_pack(inHex[ 48: 52])	        #qann
            out += '$'
            out += trt_pack(inHex[ 52: 56])	        #qmoi
            out += '$'
            out += trt_pack(inHex[ 56: 60])	        #qjou
            out += '$'
            out += inChr[ 30: 31]					#ccer
            out += '$'
            out += trt_packdec(inHex[ 62: 70], 4)   #qexe
            out += '$'
            out += trt_packdec(inHex[ 70: 78], 4)   #qex2
            out += '$'
            out += trt_pack(inHex[ 78: 84])	        #cpay
            out += '$'
            out += trt_date(inHex[ 84: 93])	        #dmaj
     
            outFile.write(out + '\n')
     
        inFile.close(), outFile.close();
     
    #================================
    def trt_StringIO():
        """   traitement act """
     
        import cStringIO
     
        i = 0
        inFile = open("{0}/{1}.bin".format('D:/py', 'act'), 'r')
        outFile = open("{0}/{1}.2.ans".format('D:/py', 'act'), 'w')
        while 1:
            inChr = inFile.read(47)
            if inChr == '' : 		break
            inHex = binascii.hexlify(inChr)
            out = cStringIO.StringIO()
     
            out.write(trt_pack(inHex[  0:  6]))	        #matricule
            out.write('$')
            out.write(trt_date(inHex[  6: 15]))	        #dins
            out.write('$')
            out.write(inChr[  8:  9])					#cins
            out.write('$')
            out.write(trt_date(inHex[ 18: 27]))	        #dces
            out.write('$')
            out.write(inChr[ 14: 15])					#cces
            out.write('$')
            out.write(inChr[ 15: 16])					#natv
            out.write(inChr[ 16: 17])
            out.write(inChr[ 17: 18])
            out.write('$')
            out.write(inChr[ 18: 19])					#catv
            out.write('$')
            out.write(trt_pack(inHex[ 38: 42]))	        #ibar
            out.write('$')
            out.write(trt_pack(inHex[ 42: 48]))	        #istr
            out.write('$')
            out.write(trt_pack(inHex[ 48: 52]))	        #qann
            out.write('$')
            out.write(trt_pack(inHex[ 52: 56]))	        #qmoi
            out.write('$')
            out.write(trt_pack(inHex[ 56: 60]))	        #qjou
            out.write('$')
            out.write(inChr[ 30: 31])					#ccer
            out.write('$')
            out.write(trt_packdec(inHex[ 62: 70], 4))   #qexe
            out.write('$')
            out.write(trt_packdec(inHex[ 70: 78], 4))   #qex2
            out.write('$')
            out.write(trt_pack(inHex[ 78: 84]))	        #cpay
            out.write('$')
            out.write(trt_date(inHex[ 84: 93]))	        #dmaj
            out.write('\n')
            outFile.write(out.getvalue())
            out.close()
     
        inFile.close(), outFile.close()
     
    #================================
    def trt_pack(s):
    	"""  traitement des entiers """
    	if s[-1] == 'f' :
    		return '+' + s[:-1]
    	elif s[-1] == 'd'  :	
    		return '-' + s[:-1]
    	else :
    		return '%' + s[:-1]	
     
    #================================
    def trt_packdec(s, d):
    	"""  traitement des nombres décimaux """ 
     
    	if s[-1] == 'f' :
    		sign = '+'
    	elif [-1] == 'd'  :
    		sign = '-'
    	else :
    		sign = '%'
    	return sign + s[:len(s)-d-1] + ',' + s[len(s)-d-1:-1]
     
    #================================
    def trt_date(d):
    	"""  traitement des dates """
     
    	aaaa = d[1:5]
    	mm = d[5:7]
    	jj = d[7:]
     
    	if aaaa == '0000' : 			
    		return ''.ljust(10, ' ')
    	elif mm == '00' or jj == '00' :	
    		return '01/01/' + aaaa
    	else :
    		return jj + '/' + mm + '/' + aaaa
    >> Je parlais d'un buffer, pas d'une structure.

    Je n'ai pas trouvé comment décrire ce buffer autrement qu'avec cette structure ctypes ?

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    34
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 34
    Par défaut
    en cherchant un peu j'ai trouvé memoryview.

    ça ne va pas plus vite, mais c'est plus propre.
    Inconvénient : il faut indiquer la longueur des enregistrements en sortie ainsi que la position et la longueur des champs dans le buffer d'écriture.

    ça complique un peu le générateur de code, mais c'est jouable.

    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
    def trt_avoc_act23():
        """   traitement act """
     
        i = 0
        inFile = open("{0}/{1}.bin".format('D:/py', 'act'), 'r')
        outFile = open("{0}/{1}.2.ans".format('D:/py', 'act'), 'w')
     
        data = bytearray(('$' * 105) + '\n')
        v = memoryview(data)
     
        while 1:
            inChr = inFile.read(47)
            if inChr == '' : 		break
            inHex = binascii.hexlify(inChr)
     
            v[0:6] = trt_pack(inHex[  0:  6])	        #matricule
            v[7:17] = trt_date(inHex[  6: 15])	        #dins
            v[18:19] = inChr[  8:  9]					#cins
            v[20:30] = trt_date(inHex[ 18: 27])	        #dces
            v[31:32] = inChr[ 14: 15]					#cces
            v[33:36] = inChr[ 15: 18]					#natv
            v[37:38] = inChr[ 18: 19]					#catv
            v[39:43] = trt_pack(inHex[ 38: 42])	        #ibar
            v[44:50] = trt_pack(inHex[ 42: 48])	        #istr
            v[51:55] = trt_pack(inHex[ 48: 52])	        #qann
            v[56:60] = trt_pack(inHex[ 52: 56])	        #qmoi
            v[61:65] = trt_pack(inHex[ 56: 60])	        #qjou
            v[66:67] = inChr[ 30: 31]					#ccer
            v[68:77] = trt_packdec(inHex[ 62: 70], 4)   #qexe
            v[78:87] = trt_packdec(inHex[ 70: 78], 4)   #qex2
            v[88:94] = trt_pack(inHex[ 78: 84])	        #cpay
            v[95:105] = trt_date(inHex[ 84: 93])        #dmaj
            outFile.write(v.tobytes())
     
        inFile.close(), outFile.close()

  20. #20
    Membre émérite
    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
    Par défaut
    J'ai fait pas mal d'essais de mon côté, et pas mal de surprises également...

    La première, c'est que Python3 semble trèèèèès lent avec ctypes.c_buffer, comparé à Python2.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    antoine@Aspyct:~$ time python3 buffer.py 
     
    real	0m3.640s
    user	0m3.630s
    sys	0m0.000s
    antoine@Aspyct:~$ time python buffer.py 
     
    real	0m0.439s
    user	0m0.400s
    sys	0m0.020s
    J'ai testé avec bytearray également. Étonnant que ce soit plus lent que les concaténations... à mon avis c'est à cause des objets slice pour indexer le tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    antoine@Aspyct:~$ time python bytearray.py 
     
    real	0m0.316s
    user	0m0.290s
    sys	0m0.020s
    antoine@Aspyct:~$ time python concat.py 
     
    real	0m0.211s
    user	0m0.210s
    sys	0m0.000s
    Reste l'option du module C si c'est trop lent.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Comment obtenir offset de String dans une chaine
    Par L4BiN dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 09/07/2009, 13h42
  2. Réponses: 2
    Dernier message: 03/10/2005, 16h23
  3. Réponses: 2
    Dernier message: 14/01/2005, 15h40
  4. comment vider une chaine de caractère
    Par gaut dans le forum C
    Réponses: 13
    Dernier message: 12/09/2003, 11h30
  5. Réponses: 2
    Dernier message: 06/12/2002, 07h50

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