TypeError: unhashable type: 'peticion' python



  • I'm doing a program to analyze web-slots from an exported Wireshark file. The function in which I am working right now reads the file with the objective of making a count of the different requests it contains and how many times it is repeated each.

    So a record would contain the fields "IP origin", "IP Destination", "Protocol", "No"

    The problem is I'm doing it on python and I'm a complete noob.

    The logical description of the idea is that a loop runs through the file and for each line generates a type object peticion.

    Then the program looks if that request, we'll call pIt's on a list called requests.

    If so, go to the next line of the file. If not, open another loop that runs through the lines of the file, again creating an object for each line.

    The loop compares every created object, which we will call c object p, and if they are equal sum 1 to the number of repetitions of object p.

    When the loop has traveled the entire file is added p with your repeat count to the list of requests.

    During the next tour the program will ignore the lines that are the same as that we have saved, as it is on the list.

    The case is that in the first loop I miss this mistake:

    File "D:\Utiles\Scripts\FuncPet.py", line 18, in petAglom if p in list: TypeError: unhashable type: 'peticion'

    I have sought information about it and I have seen that to go through a list it has to have a "key-value" format and that the key is immutable, or something. According to what I've seen, it makes me this mistake because the set() class is mutable.

    The thing is, I don't know if I understood it right, and even so I don't know what to change to fix it.

    Here I leave the code:

    FuncPEt.py (file with functions related to agglomerated requests):

    import sys
    from .peticionesClass import peticion
    

    def petAglom(archivo):
    lista = set()
    non_interested = ["ARP", "Protocol"]

    with open(archivo) as file:
        for line in file.readlines():
            try:
                partes = line.split(",")
                source = partes[2][1:-1]
                destination = partes[3][1:-1]
                protocol = partes[4][1:-1]
                info = partes[6][1:-1]
                if protocol not in non_interested:
                    p = peticion(source,destination,protocol)
               -----if p in lista:-------
                        pass
                    else:
                        for line in file.readlines():
                            try:
                                prts = line.split(",")
                                src = prts[2][1:-1]
                                dst = prts[3][1:-1]
                                prtcl = prts[4][1:-1]
                                inf = prts[6][1:-1]
    
                                if prtcl not in non_interested:
                                    c=peticion(src,dst,prtcl)
                                    if c == p:
                                        p.NoTimes += 1
    
                            except ValueError:
                                # Ignoramos cualquier error generado por split
                                pass
                        lista.add(p)
    
            except ValueError:
                # Ignoramos cualquier error generado por split
                pass
    
    return lista
    

    def printPetAglom(archivo):
    lista = petAglom(archivo)
    print('"Origen","Destino","Protocolo","Nº"')
    for pet in lista:
    print(pet)

    def savePetAglom(archivo):
    lista = petAglom(archivo)
    with open("PeticionesAglomeradas.csv","w") as f:
    f.write('"Origen","Destino","Protocolo","Nº"'+ '\n')
    for pet in lista:
    f.write(print(pet)+'\n')

    print('Hecho.')
    

    The line that's in... It's the one that shoots my mistake right now.

    requestsClass.py:

    class peticion():
    srcIP = ""
    dstIP = ""
    prtcl = ""
    info = ""
    NoTimes = 0

    def __init__(self,src,dst,prt):
        self.srcIP=src
        self.dstIP=dst
        self.prtcl=prt
    
    
    def __str__(self):
        return f'"{self.srcIP}","{self.dstIP}","{self.prtcl}","{self.NoTimes}"'
    
    
    def __eq__(self,peticion):
        if self.srcIP == peticion.srcIP and self.dstIP == peticion.dstIP and self.prtcl == peticion.prtcl:
            return True
        else:
            return False
    

    I hope someone can help me.

    Thank you so much!



  • One solution is to add the beat hash in the requested class,

    def __hash__(self):
        return hash((self.srcIP, self.dstIP, self.prtcl))
    

    By defining it you already evaluate the condition correctly.




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2