TypeError: can't pickle _thread.lock objects

前端 未结 3 1580
没有蜡笔的小新
没有蜡笔的小新 2020-12-02 20:15

Trying to run two different functions at the same time with shared queue and get an error...how can I run two functions at the same time with a shared queue? This is Python

相关标签:
3条回答
  • 2020-12-02 20:23

    I had the same problem with Pool() in Python 3.6.3.

    Error received: TypeError: can't pickle _thread.RLock objects

    Let's say we want to add some number num_to_add to each element of some list num_list in parallel. The code is schematically like this:

    class DataGenerator:
        def __init__(self, num_list, num_to_add)
            self.num_list = num_list # e.g. [4,2,5,7]
            self.num_to_add = num_to_add # e.g. 1 
    
            self.run()
    
        def run(self):
            new_num_list = Manager().list()
    
            pool = Pool(processes=50)
            results = [pool.apply_async(run_parallel, (num, new_num_list)) 
                          for num in num_list]
            roots = [r.get() for r in results]
            pool.close()
            pool.terminate()
            pool.join()
    
        def run_parallel(self, num, shared_new_num_list):
            new_num = num + self.num_to_add # uses class parameter
            shared_new_num_list.append(new_num)
    

    The problem here is that self in function run_parallel() can't be pickled as it is a class instance. Moving this parallelized function run_parallel() out of the class helped. But it's not the best solution as this function probably needs to use class parameters like self.num_to_add and then you have to pass it as an argument.

    Solution:

    def run_parallel(num, shared_new_num_list, to_add): # to_add is passed as an argument
        new_num = num + to_add
        shared_new_num_list.append(new_num)
    
    class DataGenerator:
        def __init__(self, num_list, num_to_add)
            self.num_list = num_list # e.g. [4,2,5,7]
            self.num_to_add = num_to_add # e.g. 1
    
            self.run()
    
        def run(self):
            new_num_list = Manager().list()
    
            pool = Pool(processes=50)
            results = [pool.apply_async(run_parallel, (num, new_num_list, self.num_to_add)) # num_to_add is passed as an argument
                          for num in num_list]
            roots = [r.get() for r in results]
            pool.close()
            pool.terminate()
            pool.join()
    

    Other suggestions above didn't help me.

    0 讨论(0)
  • 2020-12-02 20:24

    multiprocessing.Pool - PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed

    Move the queue to self instead of as an argument to your functions package and send

    0 讨论(0)
  • 2020-12-02 20:38

    You need to change from queue import Queue to from multiprocessing import Queue.

    The root reason is the former Queue is designed for threading module Queue while the latter is for multiprocessing.Process module.

    For details, you can read some source code or contact me!

    0 讨论(0)
提交回复
热议问题