Context manager: Difference between revisions

From Helpful
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 1: Line 1:
{{programming}}
{{programming}}


Context managers bolt hook in some implied extra code, onto a code blocks, via syntactic sugar.
Context managers are syntactic sugar you use on a code block, to bolt in some implied extra code.




 
They seem largely used to do resource cleanup more implicitly and automatically,
Often used to do some resource cleanup more implicitly and automatically, but there are various other uses.  
but there are various other uses.  


<!--
<!--

Revision as of 12:15, 6 November 2023

Some fragmented programming-related notes, not meant as introduction or tutorial

Data: Numbers in computers ·· Computer dates and times ·· Data structures

Wider abstractions: Programming language typology and glossary · Generics and templating ·· Some abstractions around programming · · Computational complexity theory notes · Synchronous, asynchronous · First-class citizen

Syntaxy abstractions: Constness · Memory aliasing · Binding, assignment, and such · Closures · Context manager · Garbage collection

Sharing stuff: Communicated state and calls · Locking, data versioning, concurrency, and larger-scale computing notes

Language specific: Python notes ·· C and C++ notes · Compiling and linking ·· Lua notes

Teams and products: Programming in teams, working on larger systems, keeping code healthy · Benchmarking, performance testing, load testing, stress testing, etc. · Maintainability

More applied notes: Optimized number crunching · File polling, event notification · Webdev · GUI toolkit notes

Mechanics of duct taping software together: Automation, remote management, configuration management · Build tool notes · Installers


Context managers are syntactic sugar you use on a code block, to bolt in some implied extra code.


They seem largely used to do resource cleanup more implicitly and automatically, but there are various other uses.



Python

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.


For example:

with open(filename) as file:
   file_data = file.read()

is roughly equivalent to

try:
   file = open(filename)
   file_data = file.read()
finally:
   file.close()

...because the built-in open() already implements the interface we're about to describe (and e.g. does a close in its __exit__).


At its core, the with statement takes an object; that object's its

  • __enter__() will be called at the start of the block
and returns the thing that will be assigned
  • __exit__() will be called afterwards
also if an exception is raised (so is much like a try-finally)



If open() were unaware of this interface, we might add it like in the following example (as it is, this example is redundant and pointless. A better example would be a database connection, but it'd take a few more lines to actually be runnable code)

You can write this more manually like:

class Test(object):
    def __init__(self, filename):  # __init__ isn't part of concept, but is how you get parameters in 
        self.filename = filename   #  (without which you'll find it hard to get __enter__ to return something useful to you)

    def __enter__(self):
        print('__enter__')
        self.fob = open(self.filename)
        return self.fob

    def __exit__(self, exc_type,exc_value, exc_traceback):
        print('__exit__')
        self.fob.close()

with Test('textfile') as t:
    print( t )


You may prefer to use the @contextlib.contextmanager decorator, which is mild trickery where you write a generator, everything before the yield is effectively run as part of __enter__, and that exactly-one yield is what gets assigned

@contextlib.contextmanager
def test(filename): # 
    f = open(filename)
    try:
        yield f
    finally:
        f.close()

with test('textfile') as t:
    print( t )


Notes:

  • there is also a way to ease creating a mixin

Javascript

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.

Nothing built in, but because ES6 has generators(good support since ~2017) you can insert both some before and after code, much like that second python example.

To copy-paste from [1]:

function* usingGroup() {
   console.group()
   try {
     yield;
   } finally {
     console.groupEnd();
   }
}

for(const _ of usingGroup()) {
   console.log('inside a group')
}

The same page also mentions a library to make this a little easier, imitating python.

C#

This article/section is a stub — some half-sorted notes, not necessarily checked, not necessarily correct. Feel free to ignore, or tell me about it.