masklinn í dag viðrar vel til loftárása | xilebo a écrit :
- mauvaise gestion des exceptions. Bien que ca existe en C++, je ne les ai jamais vraiment utilisées (on peut s'en passer ) sauf que c'est un peu obligatoire en python. Je ne sais pas quoi mettre dans try, except, else, et finally ( voir fonction r_parse_hex et r_parse_xml )
|
Rien du tout, sauf si tu veux spécifiquement gérer les erreurs correspondantes. Ici au lieu du try/finally tu voudras utiliser un "context manager"(similaire mais pas identique au RAII de C++) géré via with, et à la limite un gros try/except autour du tout si tu veux planquer les erreurs sans spécialement les gérer mais aussi sans arrêter complètement le processing. Le "else" est également assez peu utilisé, ici on mettrait plus tout dans le body, on bien on utiliserait un early return:
Code :
def r_parse_hex(e): try: with open(e['hex'], 'rb') as f: ret = f.read(0x400) # lire entete eeprom e['chk_hex'] = ret[0x212:0x214][:-1].hex().upper() except: print("Error opening", e['hex'], file=sys.stderr) return e
| Prendre un objet qu'on modifie en place et renvoie c'est aussi un peu étrange, il y a des contextes où ça se fait (builders) mais ici ça semble pas trop être le cas.
xilebo a écrit :
- j'ai un peu bidouillé pour formatter ma string venant du fichier xml correctement en hex : j'ai paddé avec des 0 pour être sur d'avoir 4 caractères ( e['chk_xml'] = chk.attrib['hexa'].rjust(4,'0') )
|
Bah si t'as besoin de 4 char et que ton entrée peut en avoir moins, faut padder. Tu pourrais le faire avec un format à la place mais tu gagnerais rien.
xilebo a écrit :
- j'ai encore plus bidouiller pour formater la string venant du fichier hex :
Code :
- ret = f.read(0x400) # lire entete eeprom
- e['chk_hex'] = ret[0x212:0x214][:-1].hex().upper()
|
* je lis 1024 octets ( c'est normalement sur mais j'ai pas géré si inférieur ) * mon checksum est à l'octet 0x212 + 0x213 mais à l'envers ( little endian ) , je l'inverse en rajoutant puis transforme en string avec hex(), puis je passe en majuscule avec upper()
|
Alternativement tu peux parser ton truc avec struct.unpack (genre <H) et le formatter comme nécessaire derrière. Ou bien pas le formatter et parser la sortie de ton fichier XML avec int(val, 16).
xilebo a écrit :
- mon parcours de fichier est comme ca :
Code :
- for root,dirs,files in os.walk("." ):
- for name in files:
- fname = os.path.join(root, name)
- base , ext = os.path.splitext( name)
- if ext==".hex" or ext==".xml":
- r_insert( result , ext[1:] , base , fname )
| mais j'aurais préféré un truc du genre :
Code :
- [ os.path.join(dp, f) for dp, dn, fn in os.walk(os.path.expanduser("." )) for f in fn]
|
sauf que je ne sais pas comment rajouter dans la ligne du code permettant de filtrer d'une part les hex/xml, et appeler une fonction d'autre part à chaque itération pour effectuer le traitement.
|
S'pas trop possible à cause de la manière dont t'as structuré ton processing: ton r_insert va pas nécessairement générer de nouveaux éléments, et va potentiellement aller altérer des trucs en place à la place. Si tu veux faire un truc du style, je suggère d'itérer juste sur les bases et pour chaque base aller chercher les données dans le fichier hex et le fichier xml en parallèle, ça évite des bricolages genre aller faire des recherches linéaires dans une liste. Apprends aussi à utiliser les fonctions de formattage Python (%, format ou f-strings). Pas testé, mais un truc genre:
Code :
def parse_xml(path): try: doc = ET.parse(path) return ( doc.find('pnp_fin').attrib['label'], int(doc.find('pnp_checksum'].attrib['hexa'], 16) ) except Exception as e: print(f"Failed to read {path}: {e}", file=sys.stderr) return None, -1 def parse_hex(path): try: with open(path, 'rb'): [result] = struct.unpack_from("<H", path.read(0x400), 0x212) return result except Exception as e: print(f"Failed to read {path}: {e}", file=sys.stderr) if __name__ == '__main__': for root, _, files in os.walk('.'): for name in fnmatch.filter(files, '*.xml'): fbase, _ = os.path.splitext(os.path.join(root, files)) label, checksum_xml = parse_xml(fbase + '.xml') checksum_hex = parse_hex(fbase + '.hex') if check_xml == check_hex: print(f"GOOD \t{label:>16}\t(chk={check_xml})" ) else: print(f"BAD \t{label:>16}\t(xml={check_xml},hex={check_hex})" )
| Si tu veux absolument un itérateur ou une listcomp c'est moyen pratique à cause des manipulations de path avant de parser les fichiers. Ça serait faisable avec un helper ou bien la technique de la liste unaire (for foo in [val] c'est comme faire foo = 1 au milieu de la listcomp) mais je recommande pas spécialement. D'ailleurs en regardant ce code, je me dis que la gestion d'erreur devrait aller autour des appels à parse_xml et parse_hex, si l'un des deux foire l'autre est pas utile:
Code :
def parse_xml(path): doc = ET.parse(path) return ( doc.find('pnp_fin').attrib['label'], int(doc.find('pnp_checksum'].attrib['hexa'], 16) ) def parse_hex(path): with open(path, 'rb'): [result] = struct.unpack_from("<H", path.read(0x400), 0x212) return result if __name__ == '__main__': for root, _, files in os.walk('.'): for name in fnmatch.filter(files, '*.xml'): fbase, _ = os.path.splitext(os.path.join(root, files)) try: label, checksum_xml = parse_xml(fbase + '.xml') checksum_hex = parse_hex(fbase + '.hex') except Exception as e: print(f"ERROR failed to load {fbase}: {e}" ) else: if check_xml == check_hex: print(f"GOOD \t{label:>16}\t(chk={check_xml})" ) else: print(f"BAD \t{label:>16}\t(xml={check_xml},hex={check_hex})" )
|
Les fonctions de parsing s'occupent que de leur "happy path", et c'est le driver qui gère les erreurs de parsing.
Message édité par masklinn le 10-10-2018 à 21:35:00 ---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
|