2

I am trying to understand how the callback function in Pool.apply_async works, and ran into the following issue. Outside of the callback, I define

results = []

and want to use the callback to append return values from the worker process to results as the values become available.

The strange thing, though, is that this statement (in the callback) works :

results.append(t)

but

results += [t]

reports an unassigned reference error.

What is going on? Any insight will be greatly appreciated!

Here is the complete code :

from multiprocessing import Pool
import random

results = []

def f(t):
    return t

def cb_append_result(t):
    # reports "local variable 'results' referenced before assignment"
    # results += [t]    

    # Okay
    results.append(t)   # works

if __name__ == '__main__':
    pool = Pool() 
    t = random.random()

    pool.apply_async(f,args=(t,),callback=cb_append_result)    
    pool.close()
    pool.join()
    print("Result is {}".format(results))

(ADDED) The issue has nothing to do with multiprocessing or callbacks (see answer below). But to fix the problem above, the callback function should be written as

def cb_append_result(t):
    global results
    results += [t]    
Donna
  • 1,390
  • 1
  • 14
  • 30
  • Yep - that is it! I in fact suspected something like this, but couldn't get past the fact that both `append` and `+=` logically do the same thing (change an existing object). I'll post the solution below. – Donna Jan 27 '18 at 23:33

1 Answers1

1

The solution in fact has nothing to do with multiprocessing or callbacks. The key is to use the global statement to explicitly reference a global variable.

Here is a simple code demonstrating the issue.

y = []

# doesn't work
def f(x):
    y += [x]

# works
def g(x):
    global y           # <===== Answer!!
    y += [x]

# works
def h(x):
    y.append(x)

# f(1)   # local variable 'y' referenced before assignment

g(1)     # works
print(y)

h(2)     # works
print(y)

with the output :

[1]
[1, 2]

So in fact, the callback business, etc was all obfuscation. I've edited my original post.

Donna
  • 1,390
  • 1
  • 14
  • 30