Sign Up

Have an account? Sign In Now

Sign In

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have a permission to ask a question, You must login to ask question.

Forgot Password?

Need An Account, Sign Up Here
Sign InSign Up

ErrorCorner

ErrorCorner Logo ErrorCorner Logo

ErrorCorner Navigation

  • Home
  • Contact Us
  • About Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Contact Us
  • About Us
Home/ Questions/Q 373
Next
Answered
Kenil Vasani
Kenil Vasani

Kenil Vasani

  • 646 Questions
  • 567 Answers
  • 77 Best Answers
  • 26 Points
View Profile
  • 5
Kenil Vasani
Asked: December 10, 20202020-12-10T22:51:11+00:00 2020-12-10T22:51:11+00:00In: Python

Python Multiprocessing Pool Map: AttributeError: Can’t pickle local object

  • 5

I have a method inside a class that needs to do a lot of work in a loop, and I would like to spread the work over all of my cores.

I wrote the following code, which works if I use normal map, but with pool.map returns an error.

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)

class OtherClass:
  def run(sentence, graph):
    return False

class SomeClass:
  def __init__(self):
    self.sentences = [["Some string"]]
    self.graphs = ["string"]

  def some_method(self):
      other = OtherClass()

      def single(params):
          sentences, graph = params
          return [other.run(sentence, graph) for sentence in sentences]

      return list(pool.map(single, zip(self.sentences, self.graphs)))


SomeClass().some_method()

Error:

AttributeError: Can’t pickle local object ‘SomeClass.some_method..single’

Why can’t it pickle single? I even tried to movesingle to the global module scope (not inside the class – makes it independent of the context):

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)

class OtherClass:
  def run(sentence, graph):
    return False


def single(params):
    other = OtherClass()
    sentences, graph = params
    return [other.run(sentence, graph) for sentence in sentences]

class SomeClass:
  def __init__(self):
    self.sentences = [["Some string"]]
    self.graphs = ["string"]

  def some_method(self):
      return list(pool.map(single, zip(self.sentences, self.graphs)))


SomeClass().some_method()

and I get the following error:

AttributeError: Can’t get attribute ‘single’ on module ‘main‘ from ‘…/test.py’

multiprocessingpythonpython-multiprocessing
  • 1 1 Answer
  • 9 Views
  • 0 Followers
  • 0
Answer
Share
  • Facebook

    1 Answer

    • Voted
    1. Kenil Vasani

      Kenil Vasani

      • 646 Questions
      • 567 Answers
      • 77 Best Answers
      • 26 Points
      View Profile
      Best Answer
      Kenil Vasani
      2020-12-10T22:47:00+00:00Added an answer on December 10, 2020 at 10:47 pm

      Error 1:

      AttributeError: Can’t pickle local object
      ‘SomeClass.some_method..single’

      You solved this error yourself by moving the nested target-function single() out to the top-level.

      Background:

      Pool needs to pickle (serialize) everything it sends to its worker-processes (IPC). Pickling actually only saves the name of a function and unpickling requires re-importing the function by name. For that to work, the function needs to be defined at the top-level, nested functions won’t be importable by the child and already trying to pickle them raises an exception (more).


      Error 2:

      AttributeError: Can’t get attribute ‘single’ on module ‘main’ from
      ‘…/test.py’

      You are starting the pool before you define your function and classes, that way the child processes cannot inherit any code. Move your pool start up to the bottom and protect (why?) it with if __name__ == '__main__':

      import multiprocessing
      
      class OtherClass:
        def run(self, sentence, graph):
          return False
      
      
      def single(params):
          other = OtherClass()
          sentences, graph = params
          return [other.run(sentence, graph) for sentence in sentences]
      
      class SomeClass:
         def __init__(self):
             self.sentences = [["Some string"]]
             self.graphs = ["string"]
      
         def some_method(self):
            return list(pool.map(single, zip(self.sentences, self.graphs)))
      
      if __name__ == '__main__':  # <- prevent RuntimeError for 'spawn'
          # and 'forkserver' start_methods
          with multiprocessing.Pool(multiprocessing.cpu_count() - 1) as pool:
              print(SomeClass().some_method())
      

      Appendix

      …I would like to spread the work over all of my cores.

      Potentially helpful background on how multiprocessing.Pool is chunking work:

      Python multiprocessing: understanding logic behind chunksize

      • 5
      • Share
        Share
        • Share on Facebook
        • Share on Twitter
        • Share on LinkedIn
        • Share on WhatsApp

    You must login to add an answer.

    Forgot Password?

    Sidebar

    Ask A Question
    • Popular
    • Kenil Vasani

      SyntaxError: invalid syntax to repo init in the AOSP code

      • 5 Answers
    • Kenil Vasani

      xlrd.biffh.XLRDError: Excel xlsx file; not supported

      • 3 Answers
    • Kenil Vasani

      Homebrew fails on MacOS Big Sur

      • 3 Answers
    • Kenil Vasani

      runtimeError: package fails to pass a sanity check for numpy ...

      • 3 Answers
    • Kenil Vasani

      Unable to resolve dependency tree error when installing npm packages

      • 2 Answers

    Explore

    • Most Answered
    • Most Visited
    • Most Voted
    • Random

    © 2020-2021 ErrorCorner. All Rights Reserved
    by ErrorCorner.com