2017-05-19 2 views
0

Je ne suis pas sûr de savoir comment utiliser struct.unpack pour voir les données dans le bytearray qui est envoyé parce que les données ne viennent pas d'une manière fixe. Il s'agit d'un format décimal condensé de longueur variable, terminé par un caractère hexadécimal. Le type de données est SQL_DECIMAL.Je ne peux pas décompresser les données dans mon convertisseur de sortie pyodbc

Par exemple, si je me attends à 123, je vois les valeurs ByteArray imprimés \ x12 \ X3e ......

J'utilise Python 3.4.3, 4.0.1 pyodbc sur Win 7

+0

Donc 1234 serait '\ x12 \ x34' et 12345 serait' \ x12 \ x34 \ x5e'? –

+0

Oui. 1234 serait \ x12 \ x34 \ xe0. BTW, j'ai écrit du code pour analyser les nybbles, mais je veux quelque chose de pythonique. – ZevGriner

Répondre

0

Je ne sais pas si cela se qualifie comme « Pars [ant] les quartets » ou est « pythonique » assez pour vous, mais cela semble fonctionner:

import itertools 


def convert_packed_decimal(byte_stream): 
    digit_list = list(itertools.chain.from_iterable([[(b & 0xF0) >> 4, b & 0xF] for b in byte_stream])) 
    num_digits = digit_list.index(0xE) 
    return sum([digit_list[i] * 10 ** (num_digits - i - 1) for i in range(num_digits)]) 


if __name__ == '__main__': 
    print(convert_packed_decimal(b'\x12\x34\xe0')) 
    print(convert_packed_decimal(b'\x90\x21\x0e')) 

pour les données de test b'\x12\x34\xe0', la première ligne de la fonction utilise une compréhension de la liste à e Xtract les chiffres individuels dans une liste imbriquée

[[1,2],[3,4],[14,0]] 

puis list(itertools.chain.from_iterable(... aplatit dehors dans une simple liste.

[1,2,3,4,14,0] 

La deuxième ligne trouve l'indice de la terminaison 0xE (décimal 14), nous donnant le nombre de chiffres à traiter (4, dans ce cas).

La troisième ligne utilise une compréhension de liste pour traiter chaque chiffre, en le multipliant par la puissance de 10 correspondant à sa position dans la liste,

[1 * 1000, 2 * 100, 3 * 10, 4 * 1] 

puis sum(... les additionne.