How to access (and edit) variables from a callback function?

I use Boto to access Amazon S3. And to download files, I can assign a callback function. The problem is that I cannot access the necessary variables from this callback function until I make them global. In the other hand, if I make them global, they are also global for all other Celery tasks (until I restart Celery), since the file is downloaded from the Celery task.

Here is a function that downloads a JSON file with information on the progress of the video conversion.

def upload_json():
    global current_frame
    global path_to_progress_file
    global bucket
    json_file = Key(bucket)
    json_file.key = path_to_progress_file
    json_file.set_contents_from_string('{"progress": "%s"}' % current_frame,
    cb=json_upload_callback, num_cb=2, policy="public-read")

And here there are 2 callback functions for loading frames generated by ffmpeg during video conversion, and a JSON file with progress information.

# Callback functions that are called by get_contents_to_filename.
# The first argument is representing the number of bytes that have
# been successfully transmitted from S3 and the second is representing
# the total number of bytes that need to be transmitted.
def frame_upload_callback(transmitted, to_transmit):
    if transmitted == to_transmit:
        upload_json()
def json_upload_callback(transmitted, to_transmit):
    global uploading_frame
    if transmitted == to_transmit:
        print "Frame uploading finished"
        uploading_frame = False
Theoretically, I can pass the uploading_frame variable to the upload_json function, but it will not receive json_upload_callback since Boto executed it.

In fact, I could write something like this.

In [1]: def make_function(message):
   ...:     def function():
   ...:         print message
   ...:     return function
   ...: 

In [2]: hello_function = make_function("hello")

In [3]: hello_function
Out[3]: <function function at 0x19f4c08>

In [4]: hello_function()
hello

Which, however, does not allow editing a value from a function, just allows you to read the value.

def myfunc():
    stuff = 17
    def lfun(arg):
        print "got arg", arg, "and stuff is", stuff
    return lfun

my_function = myfunc()
my_function("hello")

It works.

def myfunc():
    stuff = 17
    def lfun(arg):
        print "got arg", arg, "and stuff is", stuff
        stuff += 1
    return lfun

my_function = myfunc()
my_function("hello")

And this gives the UnboundLocalError reference: the local variable 'stuff', indicated before the assignment.

Thank.

+5
source share
3 answers

In Python 2.x, closure is read-only. However, you can use closure by mutable value ... i.e.

def myfunc():
    stuff = [17] # <<---- this is a mutable object
    def lfun(arg):
        print "got arg", arg, "and stuff[0] is", stuff[0]
        stuff[0] += 1
    return lfun

my_function = myfunc()
my_function("hello")
my_function("hello")

Python 3.x, nonlocal , , / , , :

def myfunc():
    stuff = 17
    def lfun(arg):
        nonlocal stuff
        print "got arg", arg, "and stuff is", stuff
        stuff += 1
    return lfun

my_function = myfunc()
my_function("hello")
my_function("hello")
+12

functools.partial. , . - , dict - , bool.

from functools import partial
def callback(arg1, arg2, arg3):
    arg1[:] = [False]
    print arg1, arg2, arg3

 local_var = [True]   
 partial_func = partial(callback, local_var)

 partial_func(2, 1)
 print local_var  # prints [False]
+3

-

def myfunc():
    stuff = 17
    def lfun(arg):
        print "got arg", arg, "and stuff is", stuff
        stuff += 1
    def register_callback(lfun)

, myfunc, "stuff".

0

All Articles