We use. We forget. This is for myself so I remember the magic called Context Manager. You already must have used the "with statement" for file handling, threads, socket and other operations. I am going to talk about creating you OWN context managers.
The magic operator to be used is : @contextmanager. It can be imported from the module "contextlib"
To create a context manager, use the decorator contextlib.contextmanager
Let's now use the above context manager
Example 1:
The magic operator to be used is : @contextmanager. It can be imported from the module "contextlib"
To create a context manager, use the decorator contextlib.contextmanager
@contextlib.contextmanager def getListCounts(x): try: from collections import Counter yield Counter(x) finally: print 'No of elements in the list : %d' % len(x)
Let's now use the above context manager
Example 1:
>>> with getListCount([10, 10, 12]) as c: print "Element occurring the most is %d" % c.most_common()[0][0] Element occurring the most is 10 No of elements in the list : 3
Example 2:
>>> with getListCount([10, 10, 12]) as c: print "Element occurring the least is %d" % c.most_common()[-1][0] Element occurring the least is 12 No of elements in the list : 3
A better practical example
For devices that support ethernet, we use sockets to communicate . Basic steps are:
- Create a socket object
- Connect the socket using IP and Port
- Send some command
- Receive reply (packets)
- Close the socket connection.
In case we forget to close the socket, it's an integrating problem . May be we can prevent that using context processors. Let's see the implementation:
import contextlib import socket socket.setdefaulttimeout(3) @contextlib.contextmanager def sock_operation(IP, port): try: sock = socket.socket() sock.connect((IP, port)) yield sock finally: sock.close() with sock_operation('198.182.1.79', 5008) as sock: sock.send("\r\nXYZ\r\n") data = '' try: while True: reply = sock.recv(16) print "reply: %s" % reply data += reply except socket.timeout: print repr(data)
We can do this with classes too and that has a different approach. Result is the same but usage is a little different.
class WorkSocket: def __init__(self, ip, port): self.ip = ip self.port = port self.sock = None def __enter__(self): self.sock = socket.socket() self.sock.connect((self.ip, self.port)) return self.sock # this is what "as socket" receives def __exit__(self, exc_type, exc_val, exc_tb): self.sock.close() return False # False = don't suppress exceptions
with WorkSocket("192.168.1.1", 8080) as sock: data = sock.recv(100) ## The two dunder methods to remember __enter__ → runs when "with" block starts, returns the resource __exit__ → runs when "with" block ends, even if exception occurred
No comments:
Post a Comment