0

I have the following code:

run_in_background (
    update_contacts(data={'email': email,'access_token': g.tokens['access_token']})
)

And I have created this function to process the called function in the background:

def run_in_background(function):

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_in_executor(None, **function**, **data**)

How would I retrieve the function and the data that's being passed to it?

  • Possible duplicate of [Getting method parameter names in Python](https://stackoverflow.com/questions/218616/getting-method-parameter-names-in-python) – BallpointBen Nov 19 '18 at 04:30
  • that is being passed how? the funciton parameter in the `run_in_background`? – Netwave Nov 19 '18 at 04:30
  • @Netwave correct -- though I don't think the function itself will work. –  Nov 19 '18 at 04:34

1 Answers1

0

Use a decorator!

A decorator is a wrapper that takes a function as it's argument:

def decorate(func):

    def wrapper(*args, **kwargs):
        # *args and **kwargs are input vars passed to func() on its call
        return f(*args, **kwargs)
    return wrapper

@decorate
def func(arg1, arg2, **kwargs):
    #do_things

In your case, this would look like:

def run_in_background(func):
    def wrapper(*args, **kwargs):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        # remember, data is in *args (or **kwargs if it's a keyword arg)
        loop.run_in_executor(None, func, data)
        return None
    return wrapper

@run_in_background
# data is an arg or positional arg here, but could easily be data=data
def update_contents(data):
    # function logic

Edit: Not always a background process:

You could change your decorator to switch between background and not:

def run_in_background(func):
    def wrapper(*args, **kwargs):
        if background:
            # run in background
        else:
            func(data)
        return None
    return wrapper

@run_in_background
def update_contact(data, background=False):
    #contact func logic

That will allow you to keep your decorator and reduce code duplication, while giving you the flexibility to specify if you want a background process or not

C.Nivs
  • 12,353
  • 2
  • 19
  • 44
  • thanks for this response. I like the decorator approach, but sometimes I will be calling the function directly (not in the background), so how could I decorate the specific call? –  Nov 19 '18 at 04:42
  • For example, if I call it like `run_in_background ( update_contacts(data={'email': email,'access_token': g.tokens['access_token']}) )`, it still runs 'synchronously'. –  Nov 19 '18 at 04:44
  • @DavidL See my edit. if you add a `kwarg` flagging it as a background process, you can just make that code change in the decorator – C.Nivs Nov 19 '18 at 04:48
  • thanks for the update, I see how it works now. is there a way to call it directly, like I have it in the statement above, without using a decorator? –  Nov 19 '18 at 04:50
  • You would just call `update_contact(data)`, the other call is implicit. The decorator in this case will work like `decorator(update_contact(*args, **kwargs))`, even though you've called `update_contact` – C.Nivs Nov 19 '18 at 04:52
  • I tried that and it doesn't work in the background -- I put a time.sleep(10) in the function to see if it's actually running in the background. –  Nov 19 '18 at 04:54
  • Note `background` defaults to `False`, you'll have to specify it to be a background process – C.Nivs Nov 19 '18 at 04:55
  • thanks, I've accepted that answer, thanks for your help. I've asked another question specifically about how to call it as specified above -- https://stackoverflow.com/questions/53368394/put-function-in-the-background –  Nov 19 '18 at 05:03