Is there a way to do more work after a return statement?

Viewed 58350

I was a bit curious if I could do more work in a function after returning a result. Basically I'm making a site using the pyramid framework(which is simply coding in python) after I process the inputs I return variables to render the page but sometimes I want to do more work after I render the page.

For example, you come to my site and update your profile and all you care about is that its successful so I output a message saying 'success!' but after that done I want to take your update and update my activity logs of what your doing, update your friends activity streams, etc.. Right now I'm doing all that before I return the result status that you care about but I'm curious if I can do it after so users get their responses faster.

I have done multi-processing before and worst case I might just fork a thread to do this work but if there was a way to do work after a return statement then that would be simpler.

example:

def profile_update(inputs):
  #take updates and update the database 
  return "it worked"
  #do maintenance processing now.
11 Answers

You can use the Timer to schedule an event to occur asynchronously at some point in time. You can also give the interval after which the event shall occur. I hope the below code and output helps.

import time
from threading import Timer

def func():
    print("Inside func at", time.time())

def schedule_an_event():
    print(time.time())
    Timer(3, func).start()
    return "Done"

print(schedule_an_event())

Output:

1579682455.5378997
Done
Inside func at 1579682458.5382733

I like Shinto Joseph's answer the best where we use threading to split of another process. I, however, believe this example exemplifies his idea better:

import threading
from time import sleep

def math_fun(x):
    # The sleep here is simply to make it clear that this happens in the background
    sleep(1)
    print(x*20)


def fun(x):
    # Create thread to run math_fun for each argument in x 
    t = threading.Thread(target=math_fun, args=[x])
    t.setDaemon(False)
    t.start()

    print("Function has returned!")

fun(5)

Expected Output:

Function has returned!
100

Being aware that it's an old topic and already has good answers, but maybe newer users find my idea attractive as well:

def master_profile_update(inputs):
    # since input parameters are global inside the upper scope
    # i omit them from the arguments of lower nested function:
    def profile_update()
        #take updates and update the database 
        return "it worked"

    profile_update()
    #do maintenance processing now..

I've found it more conventional than decorators and contextmanagers.

It is possible to cheat with the try-except-finally structure. Example:

def function():
  try:
    #do some stuff here
    return x
  except Exception:
    #do something when an error occures
  finally:
    #do here whatever you wanna do after return

Note, that the finally statement will be executed even if an exception was caught.

i think it's what are you searching about:

def foo(): # do stuff try: return something finally: # after return

What you're asking is not possible as when you give the return statement the function scope is terminated at that point but you can try a different approach

def show_status():
  return "it worked"

def profile_update(inputs):
  #take updates and update the database 
  show_status
  #do maintainence processing now..
  return  # when you are done with the maintainence processing 
Related