Monday, September 18, 2023
HomePythonDeveloping a context supervisor in Python

Developing a context supervisor in Python


Exactly how can you produce your very own context supervisor in Python?

What is a context supervisor?

A context supervisor is a things that can be utilized in a with block to sandwich some code in between an entry activity as well as a leave activity.

Submit items can be utilized as context supervisors to immediately close the data when we’re done dealing with it:

>>> > > >  with  open(" example.txt", " w")  as  data: 
 ...      data create(" Hi, globe!")
 ...
 13
>>> > > >  data shut
 Real

Context supervisors require a __ go into __ approach as well as a __ departure __ approach, as well as the __ departure __ approach must approve 3 positional disagreements:

 course  Instance: 
     def  __ go into __( self): 
         print(" go into")

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         print(" departure")

This context supervisor simply publishes go into when the with block is gotten in as well as departure when the with block is left:

>>> > > >  with  Instance(): 
 ...      print(" Yay Python!")
 ...
 go into
 Yay Python!
 departure

Obviously, this is a rather foolish context supervisor.
Allow’s take a look at a context supervisor that in fact does something a little helpful.

A helpful context supervisor

This context supervisor briefly alters the worth of a setting variable:

 import  os

 course  set_env_var: 
     def  __ init __( self,  var_name,  new_value): 
         self var_name  =  var_name
         self new_value  =  new_value

     def  __ go into __( self): 
         self original_value  =  os environ obtain( self var_name)
         os environ[self.var_name]  =  self new_value

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         if  self original_value  is  None: 
             del  os environ[self.var_name]
         else: 
             os environ[self.var_name]  =  self original_value

The INDIVIDUAL atmosphere variable on my device presently has the worth of Trey:

>>> > > >  print(" individual env var is",  os environ["USER"])
 individual env var is trey

If we utilize this context supervisor, within its with block, the INDIVIDUAL atmosphere variable will certainly have a various worth:

>>> > > >  with  set_env_var(" INDIVIDUAL", " comparable"): 
 ...      print(" individual env var is",  os environ["USER"])
 ...
 individual env var belongs

However after the with obstruct leaves, the worth of that atmosphere variable resets back to its initial worth:

>>> > > >  print(" individual env var is",  os environ["USER"])
 individual env var is trey

This is all many thanks to our context supervisor’s __ go into __ approach as well as a __ departure __ approach, which run when our context supervisor’s with block is gotten in as well as left.

What concerning that as key phrase?

You’ll in some cases see context supervisors utilized with an as key phrase (note the as outcome listed below):

>>> > > >  with  set_env_var(" INDIVIDUAL", " comparable")  as  result: 
 ...      print(" individual env var is",  os environ["USER"])
 ...      print(" Arise from __ go into __ approach:",  result)
 ...

The as key phrase will certainly aim a provided variable name to the return worth from the __ go into __ approach:

In our situation, we constantly obtain None as the worth of our result variable:

>>> > > >  with  set_env_var(" INDIVIDUAL", " comparable")  as  result: 
 ...      print(" individual env var is",  os environ["USER"])
 ...      print(" Arise from __ go into __ approach:",  result)
 ...
 individual env var belongs
 Arise from __ go into __ approach: None

This is since our __ go into __ approach does not return anything, so it unconditionally returns the default feature return worth of None

The return worth of __ go into __

Allowed’s take a look at a context supervisor that does return something from __ go into __

Below we have actually a program called timer.py:

 import  time

 course  Timer: 
     def  __ go into __( self): 
         self beginning  =  time perf_counter()
         return  self

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         self quit  =  time perf_counter()
         self expired  =  self quit -  self beginning

This context supervisor will certainly time for how long it required to run a specific block of code (the block of code in our with block).

We can utilize this context supervisor by making a Timer things, utilizing with to run a block of code, and after that examining the expired characteristic on our Timer things:

>>> > > >  t  =  Timer()
>>> > > >  with  t: 
 ...      result  =  amount( variety( 10_000_000))
 ...
>>> > > >  t expired
 0.28711878502508625

However there’s in fact an also much shorter method to utilize this context supervisor.

We can make the Timer things as well as appoint it to a variable, all on one line of code, utilizing our with block as well as the as key phrase:

>>> > > >  with  Timer()  as  t: 
 ...      result  =  amount( variety( 10_000_000))
 ...
>>> > > >  t expired
 0.3115791230229661

This functions since our context supervisor’s __ go into __ approach returns self:

     def  __ go into __( self): 
         self beginning  =  time perf_counter()
         return  self

So it’s returning the real context supervisor challenge us which’s what obtains designated to the t variable in our with block.

Because several context supervisors track some helpful state by themselves things, it’s extremely typical to see a context supervisor’s __ go into __ approach return self

The disagreements passed to __ departure __

What concerning that __ departure __ approach?

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         self quit  =  time perf_counter()
         self expired  =  self quit -  self beginning

What are those 3 disagreements that it approves?
As well as does its return worth issue?

If an exemption takes place within a with block, these 3 disagreements passed to the context supervisor’s __ departure __ approach will certainly be:

  1. the exemption course
  2. the exemption things
  3. a traceback things for the exemption

However if no exemption takes place, those 3 disagreements will certainly all be None

Below’s a context supervisor that makes use of all 3 of those disagreements:

 import  logging

 course  LogException: 
     def  __ init __( self,  logger,  degree = logging MISTAKE,  reduce = False): 
         self logger,  self degree,  self reduce  =  logger,  degree,  reduce

     def  __ go into __( self): 
         return  self

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         if  exc_type  is  not  None: 
             information  = ( exc_type,  exc_val,  exc_tb)
             self logger log( self degree, " Exemption took place",  exc_info = information)
             return  self reduce
         return  False

This context supervisor logs exemptions as they take place (utilizing Python’s logging component).

So we can utilize this LogException context supervisor such as this:

 import  logging
 from  log_exception  import  LogException

 logging basicConfig( degree = logging DEBUG)
 logger  =  logging getLogger(" instance")

 with  LogException( logger): 
     result  =  1 /  0   # This will certainly create a ZeroDivisionError
 print(" That's completion of our program")

When an exemption takes place in our code, we’ll see the exemption logged to our console:

$ python3 log_example. py.
MISTAKE: instance: Exemption took place.
Traceback ( latest telephone call last):.
Submit "/ home/trey/ _/ log_example. py", line  8,  in << component>>.
 result  =  1/  0   # This will certainly create a ZeroDivisionError
||^||
ZeroDivisionError: department by no.
Traceback ( latest telephone call last):.
Submit "/ home/trey/ _/ log_example. py", line  8,  in << component>>.
 result  =  1/  0   # This will certainly create a ZeroDivisionError
||^||
ZeroDivisionError: department by no.

We see MISTAKE, the name of our logger ( instance), Exemption took place, and after that the traceback.

In this instance, we likewise a 2nd traceback, which was published by Python when our program collapsed.

Since our program left, it really did not in fact publish out the last line in our program ( That's completion of our program).

The return worth of __ departure __

If we had actually passed reduce= Real to our context supervisor, we’ll see something various take place:

 import  logging
 from  log_exception  import  LogException

 logging basicConfig( degree = logging DEBUG)
 logger  =  logging getLogger(" instance")

 with  LogException( logger,  reduce = Real): 
     result  =  1 /  0   # This will certainly create a ZeroDivisionError
 print(" That's completion of our program")

Currently when we run our program, the exemption is logged, yet after that our program proceeds forward after the with block:

$ python3 log_example. py.
MISTAKE: instance: Exemption took place.
Traceback ( latest telephone call last):.
Submit "/ home/trey/ _/ _/ log_example. py", line  8,  in << component>>.
 result  =  1/  0   # This will certainly create a ZeroDivisionError
||^||
ZeroDivisionError: department by no.
That' s completion of our program.

We can see That's completion of our program in fact publishes out below!

What’s taking place?

So this reduce debate, it’s utilized by our context supervisor to reduce an exemption:

 import  logging

 course  LogException: 
     ...

     def  __ departure __( self,  exc_type,  exc_val,  exc_tb): 
         if  exc_type  is  not  None: 
             information  = ( exc_type,  exc_val,  exc_tb)
             self logger log( self degree, " Exemption took place",  exc_info = information)
             return  self reduce
         return  False

If the __ departure __ approach returns something real or truthy, whatever exemption was being elevated will in fact be subdued.

By default, __ departure __ returns None, equally as every feature does by default.
If we return None, which is falsey, or False, or anything that’s falsey, __ departure __ will not do anything various from its default, which is to simply proceed increasing that exemption.

However if Real or a truthy worth is returned, the exemption will certainly be subdued

Make context supervisors with __ go into __ & & __ departure __

Context supervisors are items that operate in a with block

You can make a context supervisor by producing a things that has a __ go into __ approach as well as a __ departure __ approach.

RELATED ARTICLES

Most Popular

Recent Comments