Detailed explanation of two very practical Python decorators

  • 2021-12-13 08:49:39
  • OfStack

Directory 1. Timeout function 2. Summary of Trace function

1. Timeout function

This function is to be able to give any possible hang live function to add timeout function, this function in the preparation of external API call, web crawler, database query time is particularly useful

The code for the timeout decorator is as follows:


import signal,functools # The following two libraries will be used  
class TimeoutError(Exception): pass # Definition 1 A Exception Throw after timeout  
def timeout(seconds, error_message = 'Function call timed out'):
  def decorated(func):
    def _handle_timeout(signum, frame):
      raise TimeoutError(error_message)
    def wrapper(*args, **kwargs):
      signal.signal(signal.SIGALRM, _handle_timeout)
      signal.alarm(seconds)
      try:
        result = func(*args, **kwargs)
      finally:
        signal.alarm(0)
      return result
    return functools.wraps(func)(wrapper)
  return decorated

Use:


@timeout(5) # Define the following slowfunc Function if the 5s Forced throw if you don't return inside TimeoutError Exception End  
def slowfunc(sleep_time):
  import time
  time.sleep(sleep_time) # This function is hibernation sleep_time Seconds  
slowfunc(3) #sleep 3 Second, return normally   No anomalies 
slowfunc(10) # Be terminated  

# # Output
---------------------------------------------------------------------------
TimeoutError Traceback (most recent call last)

2. Trace function

Sometimes, for demonstration purposes or debugging purposes, we need to print out the running sequence and calling logic of each step when the program runs. Similar to the bash-x debugging function when writing bash, and then the Python interpreter does not have built-in useful functions at this time, so we will "do it ourselves and have plenty of food and clothing".

The code for the Trace decorator is as follows:


'''
 No one answers the problems encountered in study? Xiaobian created 1 A Python Learning and communication group: 725638078
 Looking for like-minded friends and helping each other , There are also good video learning tutorials and PDF E-books! 
'''
import sys,os,linecache
def trace(f):
  def globaltrace(frame, why, arg):
    if why == "call": return localtrace
    return None
  def localtrace(frame, why, arg):
    if why == "line":
      # record the file name and line number of every trace
      filename = frame.f_code.co_filename
      lineno = frame.f_lineno
      bname = os.path.basename(filename)
      print("{}({}): {}".format(  bname,
        lineno,
        linecache.getline(filename, lineno).strip('\r\n')),)
    return localtrace
  def _f(*args, **kwds):
    sys.settrace(globaltrace)
    result = f(*args, **kwds)
    sys.settrace(None)
    return result
  return _f

Use:


@trace
def xxx():
  print (1)
  print (22)
  print (333)
xxx() # Call  

# # Output
< ipython-input-4-da50741ac84e > (3): Output of print 1 # @ trace
1
< ipython-input-4-da50741ac84e > (4): Output of print 22 # @ trace
22
< ipython-input-4-da50741ac84e > (5): Output of print 333 # @ trace
333

Summarize

This article is here, I hope to give you help, but also hope that you can pay more attention to this site more content!


Related articles: