One Python Timer context manager
understand Python Context manager in
Understand and use contextlib
establish Python Timer context manager
Use Python Timer context manager
At the end
In this paper , We have learned hand in hand to teach you how to achieve a Python timer . In this paper , Yunduo Jun will understand what is Context manager and Python Of with sentence , And how to complete customization . Then extend Timer
So that it can Used as context manager . Last , Use Timer How to simplify our own code as a context manager .
The first one we created above Python Timer class , Then gradually expand us Timer
class , Its code is also relatively rich and powerful . We can't be satisfied with this , You still need some code from the template to use Timer
:
First , Instantiate the class
secondly , Call before the code block to be timed .start()
Last , Call after the code block .stop()
Python There is a unique structure , Used to call a function before and after a code block : Context manager .
understand Python Context manager in Context managers have long been Python An important part of . from PEP 343 On 2005 In introducing , And for the first time in Python 2.5 To realize . have access to with
Keyword identifies the context manager in the code :
with EXPRESSION as VARIABLE: BLOCK
EXPRESSION
Are some that return to the context manager Python expression . First, the context manager is bound to the variable name VARIABLE
On ,BLOCK
Can be any conventional Python Code block . The context manager guarantees that the program is in BLOCK
Before calling some code , stay BLOCK
Call some other code after execution . Even though BLOCK
Trigger exception , The latter will also be implemented .
The most common use of a context manager is to handle different resources , Such as file 、 Locks and database connections . The context manager is used to release and clean up resources after they are used . The following example demonstrates this only by printing lines containing colons timer.py
Basic structure . Besides , It shows that in Python Common idioms for opening files in :
with open("timer.py") as fp: print("".join(ln for ln in fp if ":" in ln))class TimerError(Exception):class Timer: timers: ClassVar[Dict[str, float]] = {} name: Optional[str] = None text: str = "Elapsed time: {:0.4f} seconds" logger: Optional[Callable[[str], None]] = print _start_time: Optional[float] = field(default=None, init=False, repr=False) def __post_init__(self) -> None: if self.name is not None: def start(self) -> None: if self._start_time is not None: def stop(self) -> float: if self._start_time is None: if self.logger: if self.name:
Be careful , Use open()
As context manager , The file pointer fp
Does not explicitly close , Can confirm fp
Automatically closed :
fp.closed
True
In this example ,open("timer.py")
Is an expression that returns the context manager . The context manager is bound to a name fp
. Context manager in print()
Valid during execution . This single line code block is in fp
In the context of .
fp
What does context manager mean ? Technically speaking , Namely fp
Realized Context Manager Protocol .Python There are many different protocols at the bottom of the language . You can think of a protocol as a contract that states what specific methods our code must implement .
The context manager protocol consists of two methods :
Called when the context associated with the context manager is entered .__enter__()
.
Called when exiting the context associated with the context manager .__exit__()
.
let me put it another way , Create your own context manager , You need to write an implementation .__enter__()
and .__exit__()
Class . try Hello, World!
The context manager example :
# studio.pyclass Studio: def __init__(self, name): self.name = name def __enter__(self): print(f" Hello {self.name}") return self def __exit__(self, exc_type, exc_value, exc_tb): print(f" See you later , {self.name}")
Studio
It's a context manager , It implements the context manager protocol , Use as follows :
from studio import Studiowith Studio(" Cloud King "): print(" Busy ...")
Hello Cloud King
Busy ...
See you later , Cloud King
First , Be careful .__enter__()
How to be called before doing something , and .__exit__()
Is called after doing something . In the example , There is no reference to the context manager , Therefore, it is not necessary to use as
Name the context manager .
Next , Be careful self.__enter__()
The return value of is restricted by as
constraint . When creating the context manager , Usually want from .__enter__()
return self
. The return value can be used as follows :
from greeter import Greeterwith Greeter(" Cloud King ") as grt: print(f"{grt.name} Busy ...")
Hello Cloud King
Cloud King Busy ...
See you later , Cloud King
Writing __exit__
Function time , Something to pay attention to , It must have these three parameters :
exc_type
: Exception types
exc_val
: outliers
exc_tb
: Abnormal error stack information
These three parameters are used for error handling in the context manager , They use sys.exc_info()
The return value of returns . When the main logic code does not report an exception , All three parameters will be None.
If an exception occurs while executing the block , Then the code will use the exception type 、 Exception instances and backtracking objects ( namely exc_type
、exc_value
and exc_tb
) call .__exit__()
. Usually , These are ignored in the context manager , Call before throwing an exception .__exit__()
:
from greeter import Greeterwith Greeter(" Cloud King ") as grt: print(f"{grt.age} does not exist")
Hello Cloud King
See you later , Cloud King
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'Greeter' object has no attribute 'age'
You can see , Even if there are errors in the code , Still printed " See you later , Cloud King "
.
Now we have a preliminary understanding of what a context manager is and how to create our own context manager . In the example above , We just want to build a context manager , But wrote a class . If you just want to implement a simple function , Writing a class is a little too complicated . Now , We just want to , If only one function can be written to implement the context manager .
This point Python I've thought about it for a long time . It provides us with a decorator , You just need to implement the function content according to its code Protocol , You can turn this function object into a context manager .
We are in accordance with the contextlib To implement a context manager , To be more intuitive, let's change the use case , Create an open file that we are familiar with (with open) Context manager for .
import [email protected] open_func(file_name): # __enter__ Method print('open file:', file_name, 'in __enter__') file_handler = open(file_name, 'r') # 【 a key 】:yield yield file_handler # __exit__ Method print('close file:', file_name, 'in __exit__') file_handler.close() returnwith open_func('test.txt') as file_in: for line in file_in: print(line)
In the decorated function , Must be a generator ( with yield
), and yield
Previous code , Equivalent to __enter__
Contents of Li .yield
Later code , Equivalent to __exit__
Contents of Li .
The above code can only achieve the first purpose of the context manager ( Management resources ), Can not achieve the second purpose ( Handling exceptions ).
If you want to handle exceptions , You can change it to the following .
import [email protected] open_func(file_name): # __enter__ Method print('open file:', file_name, 'in __enter__') file_handler = open(file_name, 'r') try: yield file_handler except Exception as exc: # deal with exception print('the exception was thrown') finally: print('close file:', file_name, 'in __exit__') file_handler.close() returnwith open_func('test.txt') as file_in: for line in file_in: 1/0 print(line)
Python In the standard library contextlib
Includes a convenient way to define a new context manager , And can be used to close objects 、 Out of the box context managers that suppress errors or even do nothing !
After understanding the general working mode of the context manager , Want to know how they help with temporal code ? Suppose if you could Run some functions before and after the code block , Then it can be simplified Python How the timer works . Actually , The context manager can automatically call... Explicitly for timing .start()
and .stop()
.
Again , Must let Timer Working as a context manager , It needs to comply with the context manager protocol , let me put it another way , It has to be implemented .__enter__()
and .__exit__()
Method to start and stop Python timer . As you can see from the current code , All the necessary functions are already available , So just add the following methods to the Timer
Class :
# [email protected] Timer: # Other code remains the same def __enter__(self): """Start a new timer as a context manager""" self.start() return self def __exit__(self, *exc_info): """Stop the context manager timer""" self.stop()
Timer Now it is a context manager . An important part of the implementation is when entering the context , .__enter__()
call .start()
start-up Python timer , And when the code leaves the context , .__exit__()
Use .stop()
stop it Python timer .
from timer import Timerimport timewith Timer(): time.sleep(0.7)
Elapsed time: 0.7012 seconds
Notice two more subtle details here :
.__enter__()
return self
,Timer example , It allows users to use as
take Timer Instance bound to variable . for example , Use with Timer() as t:
Will create points to Timer Object's variables t
.
.__exit__()
Three parameters are required , It contains information about any exceptions that occur during context execution . In the code , These parameters are packaged in a file named exc_info
In the tuple of , Then ignored , here Timer No exception handling will be attempted .
In this case, no exceptions are handled . A big feature of the context manager is , Exit regardless of the context , Will ensure that .__exit__()
. In the following example , Create divide by zero formula to simulate exception view code function :
from timer import Timerwith Timer(): for num in range(-3, 3): print(f"1 / {num} = {1 / num:.3f}")
1 / -3 = -0.333
1 / -2 = -0.500
1 / -1 = -1.000
Elapsed time: 0.0001 seconds
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
ZeroDivisionError: division by zero
Be careful , Even if the code throws an exception ,Timer The elapsed time will also be printed .
Use Python Timer context managerNow we will learn how to use Timer Context manager to time " Download data " Program . Think back to how you used Timer Of :
# download_data.pyimport requestsfrom timer import Timerdef main(): t = Timer() t.start() source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1' headers = {'User-Agent': 'Mozilla/5.0'} res = requests.get(source_url, headers=headers) t.stop() with open('dataset/datasets.zip', 'wb') as f: f.write(res.content)if __name__ == "__main__": main()
We are right now requests.get()
Call to time monitor . Using the context manager, you can make your code shorter 、 It's simpler 、 Easier to read :
# download_data.pyimport requestsfrom timer import Timerdef main(): source_url = 'https://cloud.tsinghua.edu.cn/d/e1ccfff39ad541908bae/files/?p=%2Fall_six_datasets.zip&dl=1' headers = {'User-Agent': 'Mozilla/5.0'} with Timer(): res = requests.get(source_url, headers=headers) with open('dataset/datasets.zip', 'wb') as f: f.write(res.content)if __name__ == "__main__": main()
This code is actually the same as the code above . The main difference is that there are no independent variables defined t
, There is nothing superfluous in the namespace .
Add context manager functionality to Python The timer class has several advantages :
Time saving and labor saving : Only one extra line of code is required to time the execution of the code block .
High readability : Calling the context manager is readable , You can more clearly visualize the code block you are timing .
Use Timer
As a context manager, it is almost used directly .start()
and .stop()
Just as flexible , It also has less boilerplate code .
The above is a detailed explanation of using the context manager extension Python Details of the timer , More about Python Context manager For information about timers, please pay attention to other relevant articles on the software development network !