I was trying to convert the list to a set, with the following code:
set1=set(list1)
the code was running fine, but all on a sudden started to give the following error,
set1=set(list1)
TypeError: unhashable type: 'list'
please let me know how may I resolve.
And sometimes some good running program gives error all on a sudden with no parameter changed, how may I debug it?
Your error suggests that your list contains a list. Lists are mutable and thus can't be hashed for use in a set or a dictionary. One work-around is to convert your list into a tuple using tuple(some_list), but if they're heavily nested, it becomes more complex.
Your list contains another list:
>>> set([['contained list'], 1, 2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Sets can only contain items that are hashable; any standard type that cannot be mutated is hashable, but a list is not (it can be mutated). By contrast, a tuple is not mutable and can be stored in a set.
Bugs happen, even in code that has been running fine for a while. Debug it with print statements, or better still, by using a debugger like the pdb.
If your bug only appears intermittently, use a try/except block to catch the error, then print out information or use a debugger to figure out what is going on:
try:
set1=set(list1)
except TypeError:
print 'list1 not hashable? contents: %r' % list1
# optionally: import pdb; pdb.set_trace()
raise
Related
What does TypeError: 'NoneType' object is not iterable mean? Example:
for row in data: # Gives TypeError!
print(row)
It means the value of data is None.
Explanation of error: 'NoneType' object is not iterable
In python2, NoneType is the type of None. In Python3 NoneType is the class of None, for example:
>>> print(type(None)) #Python2
<type 'NoneType'> #In Python2 the type of None is the 'NoneType' type.
>>> print(type(None)) #Python3
<class 'NoneType'> #In Python3, the type of None is the 'NoneType' class.
Iterating over a variable that has value None fails:
for a in None:
print("k") #TypeError: 'NoneType' object is not iterable
Python methods return NoneType if they don't return a value:
def foo():
print("k")
a, b = foo() #TypeError: 'NoneType' object is not iterable
You need to check your looping constructs for NoneType like this:
a = None
print(a is None) #prints True
print(a is not None) #prints False
print(a == None) #prints True
print(a != None) #prints False
print(isinstance(a, object)) #prints True
print(isinstance(a, str)) #prints False
Guido says only use is to check for None because is is more robust to identity checking. Don't use equality operations because those can spit bubble-up implementationitis of their own. Python's Coding Style Guidelines - PEP-008
NoneTypes are Sneaky, and can sneak in from lambdas:
import sys
b = lambda x : sys.stdout.write("k")
for a in b(10):
pass #TypeError: 'NoneType' object is not iterable
NoneType is not a valid keyword:
a = NoneType #NameError: name 'NoneType' is not defined
Concatenation of None and a string:
bar = "something"
foo = None
print foo + bar #TypeError: cannot concatenate 'str' and 'NoneType' objects
What's going on here?
Python's interpreter converted your code to pyc bytecode. The Python virtual machine processed the bytecode, it encountered a looping construct which said iterate over a variable containing None. The operation was performed by invoking the __iter__ method on the None.
None has no __iter__ method defined, so Python's virtual machine tells you what it sees: that NoneType has no __iter__ method.
This is why Python's duck-typing ideology is considered bad. The programmer does something completely reasonable with a variable and at runtime it gets contaminated by None, the python virtual machine attempts to soldier on, and pukes up a bunch of unrelated nonsense all over the carpet.
Java or C++ doesn't have these problems because such a program wouldn't be allowed to compile since you haven't defined what to do when None occurs. Python gives the programmer lots of rope to hang himself by allowing you to do lots of things that should cannot be expected to work under exceptional circumstances. Python is a yes-man, saying yes-sir when it out to be stopping you from harming yourself, like Java and C++ does.
Code: for row in data:
Error message: TypeError: 'NoneType' object is not iterable
Which object is it complaining about? Choice of two, row and data.
In for row in data, which needs to be iterable? Only data.
What's the problem with data? Its type is NoneType. Only None has type NoneType. So data is None.
You can verify this in an IDE, or by inserting e.g. print "data is", repr(data) before the for statement, and re-running.
Think about what you need to do next:
How should "no data" be represented? Do we write an empty file? Do we raise an exception or log a warning or keep silent?
Another thing that can produce this error is when you are setting something equal to the return from a function, but forgot to actually return anything.
Example:
def foo(dict_of_dicts):
for key, row in dict_of_dicts.items():
for key, inner_row in row.items():
Do SomeThing
#Whoops, forgot to return all my stuff
return1, return2, return3 = foo(dict_of_dicts)
This is a little bit of a tough error to spot because the error can also be produced if the row variable happens to be None on one of the iterations. The way to spot it is that the trace fails on the last line and not inside the function.
If your only returning one variable from a function, I am not sure if the error would be produced... I suspect error "'NoneType' object is not iterable in Python" in this case is actually implying "Hey, I'm trying to iterate over the return values to assign them to these three variables in order but I'm only getting None to iterate over"
It means that the data variable is passing None (which is type NoneType), its equivalent for nothing. So it can't be iterable as a list, as you are trying to do.
You're calling write_file with arguments like this:
write_file(foo, bar)
But you haven't defined 'foo' correctly, or you have a typo in your code so that it's creating a new empty variable and passing it in.
For me it was a case of having my Groovy hat on instead of the Python 3 one.
Forgot the return keyword at the end of a def function.
Had not been coding Python 3 in earnest for a couple of months. Was thinking last statement evaluated in routine was being returned per the Groovy (or Rust) way.
Took a few iterations, looking at the stack trace, inserting try: ... except TypeError: ... block debugging/stepping thru code to figure out what was wrong.
The solution for the message certainly did not make the error jump out at me.
It also depends on Python version you are using. Seeing different error message thrown in python 3.6 and python 3.8 as following which was the issue in my case
Python 3.6
(a,b) = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not iterable
Python 3.8
(a,b) = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot unpack non-iterable NoneType object
because using for loop while the result it is just one value not a set of value
pola.py
#app.route("/search")
def search():
title='search'
search_name = request.form.get('search')
search_item = User.query.filter_by(id=search_name).first()
return render_template('search.html', title=title, search_item=search_item )
search.html (wrong)
{% for p in search %}
{{ p }}
search.html (correct)
<td>{{ search_item }}</td>
i had this error with pandas in databricks.
The solution for this error was install the library in the cluster
enter image description here
It means data is None, which is not an iterable. Adding an or []* prevents the exception and doesn't print anything:
for row in data or []: # no more TypeError!
print(row)
* credits to some earlier comments; please beware that raising an exception may be a desired behavior too and/or an indicator of improper data setting.
Just continue the loop when you get None Exception,
example:
a = None
if a is None:
continue
else:
print("do something")
This can be any iterable coming from DB or an excel file.
Consider the following code:
#!/usr/bin/env python3.7
from typing import NamedTuple, Set
class Person(NamedTuple):
name: str
fred: Set[str]
p = Person("Phil", set())
print(p)
my_dict = {}
my_dict[p] = 10
print(my_dict)
which produces this error
Traceback (most recent call last):
File "./temp.py", line 14, in <module>
my_dict[p] = 10
TypeError: unhashable type: 'set'
In this case, it's sample code, and I have simplified it lots, so its
quite easy to see where the error comes from. typed.NamedTuple
obviousl calculates its hash based on all of its instances variables
and one of them is a set. When I discovered this, however, it was
painful to track down.
So, my question is, why is the error message showing this? Should it
not be TypeError: unhashable type: 'Person'. And why is the
traceback not coming from the bowels of python somewhere where the
error actually is.
NamedTuple is based on the tuple class. See collections.namedtuple()
The hash of a tuple is the combined hash of all the elements. See tupleobject.c
Since set is unhashable it is not possible to hash a tuple or NamedTuple containing a set.
And since the hashing of a set is implemented in C you don't see the traceback
I am designing a system that involves iterating through a pre-made non python standard dictionary with an iter function. I am trying to iterate through the tuples but keep getting this stupid Error. Also, this error only happens half the time, due to a bit flipping function that messes with inputs
TypeError: 'tuple' object cannot be interpreted as an integer
Probably an easy fix, can anyone spot?
Heres relevant code:
In my main program:
for tup in crusherdict.CrusherDict(db2, fields[0]):
log.write("VOTE\t{}\t{}\n".format(tup[0][0], tup[0][1]))
Place in Dictionary giving me the iter error:
def __iter__(self):
for i in range(self.__len__()):
yield self.db.fetch(entryName(self.name,i))
Heres db.fetch:
def fetch(self,key):
return self.cache[key]
And entryName:
def entryName(dict, str):
return (dict, "E", str)
Full BackTrace:
in <module>
if commands[line[0]](db, tempDict, logFile, line):
in cast
return inq(db, tempDict, logFile, ("INQ", tempDict["voterID"]))
line 100, in inq
for tup in crusherdict.CrusherDict(db3, fields[0]):
crusherdict.py", line 91, in __iter__
for i in range(self.__len__()):
TypeError: 'tuple' object cannot be interpreted as an integer
>>>
The traceback says the error happens at:
for i in range(self.__len__()):
We know that range expects an integer so this is hopeful, and indeed we can replicate the error message in Python 3:
>>> range((1,2))
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'tuple' object cannot be interpreted as an integer
Therefore __len__ is not returning an integer as it should.
Your function entryName() returns a tuple of three elements. This tuple is used by fetch as an index into your cache. Since we have to guess from the bits you provide, I'm guessing your cache is a plain list, and needs an integer index, not a tuple. (Also you're passing an int to an argument you named str, so you're definitely confused about something here.)
I have been bitten by something unexpected recently. I wanted to make something like that:
try :
thing.merge(iterable) # this is an iterable so I add it to the list
except TypeError :
thing.append(iterable) # this is not iterable, so I add it
Well, It was working fine until I passed an object inheriting from Exception which was supposed to be added.
Unfortunetly, an Exception is iterable. The following code does not raise any TypeError:
for x in Exception() :
print 1
Does anybody know why?
Note that what is happening is not related to any kind of implicit string conversion etc, but because the Exception class implements __getitem__ to return the values from the args tuple (ex.args). You can see this by the fact that you get the whole string as your first and only item in the iteration, rather than the character-by-character result you'd get if you iterate over the string.
This surprised me too, but thinking about it, I'm guessing it is for backwards compatibility reasons. Python used to (pre-1.5) lack the current class hierarchy of exceptions. Instead, strings were thrown, with (usually) a tuple argument for any details that should be passed to the handling block, i.e:
try:
raise "something failed", (42, "some other details")
except "something failed", args:
errCode, msg = args
print "something failed. error code %d: %s" % (errCode, msg)
It looks like this behavior was put in to avoid breaking pre-1.5 code expecting a tuple of arguments, rather than a non-iterable exception object. There are a couple of examples of this with IOError in the Fatal Breakage section of the above link
String exceptions have been deprecated for a while, and are gone in Python 3. Exception objects are no longer iterable in Python 3:
>>> list(Exception("test"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Exception' object is not iterable
NOT VALID. Check Brian anwser.
Ok, I just got it :
for x in Exception("test") :
print x
....:
....:
test
Don't bother ;-)
Anyway, it's good to know.
EDIT : looking to the comments, I feel like adding some explanations.
An exception contains a message you passed to during instantiation :
raise Exception("test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: test
It's fair to say that the message is what defines the Exception the best, so str() returns it :
print Exception("test")
test
Now, it happens that Exceptions are implicitly converted to string when used in something else than an Exception context.
So when I do :
for x in Exception("test") :
print x
I am iterating over the string "test".
And when I do :
for x in Exception() :
print x
I do iterate over an empty string. Tricky. Because when it comes to my issue :
try :
thing.merge(ExceptionLikeObject)
except TypeError :
...
This won't raise anything since ExceptionLikeObject is considered as a string.
Well now, we know the HOW, but I still not the WHY. Maybe the built-in Exception inherit from the built-in String ? Because as far as I know :
adding str does not make any object iterable.
I bypassed the problem by overloding iter, making it raising TypeError !
Not a problem anymore, but still a mystery.
totalCost = problem.getCostOfActions(self.actions)
Looks like you are trying to use a list as key in a dictionary or something like that. Lists are not hashable, and so they cannot be used as dictionary keys or in sets.
On another note, python gives you a stacktrace when such an error happens, and that includes file-names and line-numbers. You should be able to track down the offending code with that.
Edit About stacktraces:
cat > script.py
foo = [1,2,3]
bar = {}
bar[foo] = "Boom"
print "Never happens"
python script.py
Traceback (most recent call last):
File "script.py", line 3, in <module> // this is the file and the line-number
bar[foo] = "Boom"
TypeError: unhashable type: 'list'
You've probably attempted to use mutable objects such as lists, as the key for a dictionary, or as a member of a set. Mutable items cannot be tracked for such uses efficiently and predictably so they do not provide the hash special attribute.
The error is produced when an unhashable type is added to sets.
>>> s=set((1,2))
>>> a.add([3,4])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
I think this may be also your case. Use tuple instead of list:
>> a.add((3,4))
>>>
Maybe the line should be like this instead
totalCost = sum(map(problem.getCostOfActions,self.actions))
or if you prefer a generator expression
totalCost = sum(problem.getCostOfActions(action) for action in self.actions)
Since I can't see your code, I assumed that problem.getCostOfActions() returns the cost of a single action, as that might cause the error you are getting if self.actions is a list
Alternatively you could fix the function problem.getCostOfActions() so that it returns the total cost of a list of actions as the name suggests.
Consider adding the body of this function to your question if you want help fixing it
I had the same error with django :
food_list = ['spam' , 'more spam' , 'spam spam']
table.cum.add(food_list)
and I got error - TypeError: list objects are unhashable.
The fix is table.cum.add(*food_list)
-add * infront of list to unpack it
the model method add accepts args - (x,y,z) but not ([x,y,z])
hope it helps