Last updated: Apr 11, 2024
Reading time·2 min
The Python "TypeError: cannot pickle '_thread.lock' object" occurs when you
try to pickle a _thread.lock
object.
To solve the error, remove the _thread.lock
object before pickling.
Here is an example of how the error occurs.
import pickle import threading a_dict = { 'website': 'bobbyhadz.com', 'topic': 'Python', 'lock_object': threading.Lock() } # ⛔️ TypeError: cannot pickle '_thread.lock' object with open('example.pickle', 'wb') as file_handle: pickle.dump(a_dict, file_handle, protocol=pickle.HIGHEST_PROTOCOL)
Notice that the dictionary contains a key that points to a lock
object.
Pickling a lock
object is not allowed and so the error is raised.
The
threading.Lock
class is used to create lock
objects.
Once a thread has acquired a lock, subsequent attempts to acquire it block until it is released.
lock
object before picklingOne way to solve the error is to remove the lock
object before pickling.
import pickle import threading a_dict = { 'website': 'bobbyhadz.com', 'topic': 'Python', 'lock_object': threading.Lock() } del a_dict['lock_object'] with open('example.pickle', 'wb') as file_handle: pickle.dump(a_dict, file_handle, protocol=pickle.HIGHEST_PROTOCOL)
The code sample uses the
del
statement to remove the lock_object
key from the dictionary.
You might also have gotten the error when storing a lock
object in a list.
import pickle import threading a_list = ['bobby', 'hadz', 'com', threading.Lock()] # ⛔️ TypeError: cannot pickle '_thread.lock' object with open('example.pickle', 'wb') as file_handle: pickle.dump(a_list, file_handle, protocol=pickle.HIGHEST_PROTOCOL)
You can iterate over the list and remove all lock
objects before pickling.
import pickle import threading a_list = ['bobby', 'hadz', 'com', threading.Lock()] for item in a_list.copy(): if hasattr(item, 'release') and hasattr(item, 'locked'): a_list.remove(item) with open('example.pickle', 'wb') as file_handle: pickle.dump(a_list, file_handle, protocol=pickle.HIGHEST_PROTOCOL)
We used a for
loop to iterate over a copy of the list.
Iterating over a copy is necessary because you aren't allowed to remove items from a list while iterating over it.
On each iteration, we check if the current item is a lock
object.
If the condition is met, we remove the lock
object from the list.
__getstate__
in a classYou can also remove the lock object using a custom class.
import pickle import threading class Pickler: def __init__(self): self.website = 'bobbyhadz.com' self.topic = 'Python' self.lock_object = threading.Lock() def __getstate__(self): state = self.__dict__.copy() print(state) # 👇️ don't pickle the lock_object key del state['lock_object'] return state obj1 = Pickler() print(obj1) with open('example.pickle', 'wb') as file_handle: pickle.dump(obj1, file_handle, protocol=pickle.HIGHEST_PROTOCOL) print('success')
The object.__getstate__ method can be used to influence how instances are pickled.
The method is called and the returned object is pickled as the contents for the instance, instead of a default state.
You can learn more about the related topics by checking out the following tutorials: