Error: unhashable type: dict_keys, how to resolve?

Asked

Viewed 455 times

0

I have a code that accesses a CSV file through a function. I created a second function to change the header name of the columns (change name) and not to have to call it several times by changing the parameters of "colunaIngles" and "colunaPortugues" - a call for each column -, created a support function (change NomeSupporte) which takes the keys (Keys) and values (values) of a dictionary and passes as an argument in the call of the main function (alterName).

That is, it is a function that calls another function using the keys and values of a dictionary as parameters.

It turns out that gives the error "Typeerror: unhashable type: 'dict_keys'" and I can’t solve, I tried to convert to list and frozenset but it was unsuccessful.

Any idea how to solve?

CSV access script:

import unicodecsv

def lerCsv(arquivo):
    with open(arquivo, 'rb') as dados:
        dicionario = unicodecsv.DictReader(dados)
        return list(dicionario)

envolvimentoDiario = lerCsv('envolvimento_diario.csv')

Script with functions for changing column keys:

envolvimentoNomesColunas = {'acct': 'id_conta', 'utc_date': 'data'}

chaves = envolvimentoNomesColunas.keys()
valores = envolvimentoNomesColunas.values()


def alterarNomeSuporte(arquivo):
    for coluna in arquivo:
        alterarNome(arquivo, chaves, valores)

def alterarNome(arquivo, colunaIngles, colunaPortugues):
    for coluna in arquivo:
        coluna[colunaPortugues] = coluna[colunaIngles] (colunaPortugues) cujos valores são iguais ao da colunaIngles
        del[coluna[colunaIngles]]

alterarNomeSuporte(envolvimentoDiario)
print (envolvimentoDiario[0])

Thank you!

1 answer

0

With frozenset should work yes - the correct would be to do on these lines:

chaves = envolvimentoNomesColunas.keys()
valores = envolvimentoNomesColunas.values()

moving on to

chaves = frozenset(envolvimentoNomesColunas.keys())
valores = frozenset(envolvimentoNomesColunas.values())

In this way, the jpa "change" function receives the data as frozenset and uses it everywhere.

As I said in the comments, the names of your variables are bad - to the point that it is very difficult to keep track of your code. The suggestion is that the variable name always remembers in fact its contents. (And a lighter suggestion is that function names in variables in Pythn in general are in ores, separated by "_". This is a suggested style and each one can do as they please, but one of the reasons Python has adopted this style is that it is preferred by most people for making it easier to read).

But then, the mistake you had after switching the key search to keys with "frozenset" is precisely why when you calf the dictionary, you must convert the key to frozenset as well. If the key is a string, it will never be equal to the frozenset that we try to find.

For keys to be frozensets, you only need to do this when creating each dictionary:

def lerCsv(arquivo):
    with open(arquivo, 'rb') as dados:
        leitor = unicodecsv.DictReader(dados)
        return [{frozenset(chave): frozenset(valor) for chave, valor in linha.items()}  for linha in leitor]

However, this code, which will create the dictionaries correctly, indicates that what you are trying to do has some other problem - since the keys read by CSV Reader will always be a single string. The lists that originated your "unhashable key" error will then not be found in your dictionary, even now that we normalize key types.

In other words, even with these adjustments you should still have "Keyerror" error, but with this style of code I can’t keep up with what you’re really trying to do. My suggestion is that you use the debugger (pdb), or insert some prints into your code to understand how are the existing keys and values you want to replace - and possibly it will be possible to leave everything as strings even.

(by the way, if you are using Python3, not a "unicodecsv", only the csv standard, from the standard library)

  • Hello, so, I had already tried exactly as you said. When I convert to frozenset it returns me this error: "Keyerror: frozenset({'utc_date', 'acct'})"

  • their variable names are confused, and it is difficult to keep track of what is happening - in particular you have a "file" parameter in your functions that actually contains a list which was read in the leCSV. I strongly recommend that you go refactoring your program to media that will change the same of fforma uqe variable names make sense, otherwise it won’t be hard for other people to look at your code, as it will be complicated for you to even see this code back in a few weeks.

  • Said the above: of course for the key to exist in the dictionary, the dictionary keys have to be frozensets themselves: anywhere you create the dictionary that is called coluna within the method alterarNome, You must apply the frozenset transform before making the assignment. The names are so strange, and maybe I’m missing a part, that I can’t tell why this coluna is a dictionary "at all".

  • Ah - understood now, its variable "dictionary" in "leCSV" is not a dictionary itself, but a dictReader, and the function returns a list of dictionaries. (How about calling the variable of reader or leitor if that’s what’s inside it? ) I’ll edit the answer then. , what should Voce do.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.