Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the document-new entry Context Managers and files #4541

Merged
merged 5 commits into from
May 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
Title: 'Context Managers and Files'
Description: 'This document introduces context managers and in particular how they can be used to work with files. It details the two approaches, class-based and decorator-based, thanks to which the user can customize this experience to fit the needs of a given use case.'
Subjects:
- 'Computer Science'
- 'Data Science'
Tags:
- 'Best Practices'
- 'Classes'
- 'Decorators'
- 'Files'
CatalogContent:
- 'learn-python-3'
- 'paths/computer-science'
---
Comment on lines +1 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
---
Title: 'Context Managers and Files'
Description: 'This document introduces context managers and in particular how they can be used to work with files. It details the two approaches, class-based and decorator-based, thanks to which the user can customize this experience to fit the needs of a given use case.'
Subjects:
- 'Computer Science'
- 'Data Science'
Tags:
- 'Best Practices'
- 'Classes'
- 'Decorators'
- 'Files'
CatalogContent:
- 'learn-python-3'
- 'paths/computer-science'
---
---
Title: 'Context Managers'
Description: 'Context managers allow users to perform operations within a certain overarching context.'
Subjects:
- 'Computer Science'
- 'Data Science'
Tags:
- 'Best Practices'
- 'Classes'
- 'Decorators'
- 'Files'
CatalogContent:
- 'learn-python-3'
- 'paths/computer-science'
---


## Definition of a context managers

One might want to perform some operation within a certain overarching context, be it in the form of a time counter or a database connection or the use of a [file](https://www.codecademy.com/resources/docs/python/files). This is what **context managers** allow to do by implementing a **runtime context**, within which can be perform the wanted code and that closes automatically just after, sparing to the user the hassle of doing so. Regardless of the many different use cases a context manager can be used for, the **context manager protocol** always articulates those four functionalities: open the resource, implement the runtime context, handle the possible [exceptions](https://www.codecademy.com/resources/docs/python/errors), close the resource. The user input finds its place once the runtime context is started.
Comment on lines +17 to +19
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Definition of a context managers
One might want to perform some operation within a certain overarching context, be it in the form of a time counter or a database connection or the use of a [file](https://www.codecademy.com/resources/docs/python/files). This is what **context managers** allow to do by implementing a **runtime context**, within which can be perform the wanted code and that closes automatically just after, sparing to the user the hassle of doing so. Regardless of the many different use cases a context manager can be used for, the **context manager protocol** always articulates those four functionalities: open the resource, implement the runtime context, handle the possible [exceptions](https://www.codecademy.com/resources/docs/python/errors), close the resource. The user input finds its place once the runtime context is started.
## Definition
**Context managers** allow users to perform operations within a certain overarching context, be it in the form of a time counter or a database connection or the use of a file. They manage to do it by implementing a **runtime context**. In this context, the specified operation is first performed and then, the context automatically gets closed. This prevents the users from the hassle of closing it manually.
Regardless of the many different use cases that context managers can be used for, the **context manager protocol** always articulates four functionalities:
- Opening the resource
- Implementing the runtime context
- Handling the possible [exceptions](https://www.codecademy.com/resources/docs/python/errors)
- Closing the resource
Once the runtime context is started, the user input finds its place.


## Manipulate files with context managers

The `open()` function is the standard context manager to open, perform operations on and close files.
Comment on lines +21 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Manipulate files with context managers
The `open()` function is the standard context manager to open, perform operations on and close files.
## File Manipulation
The `open()` function is the standard context manager for opening, performing operations on and closing files:


```py
# this code will print the first four lines of the poem "L'albatros"
with open('albatros.txt','r') as poem:
for i in range(4):
print(poem.readline())

# this code will however create an error as we are already outside of the indented block and therefore no longer within the context that had been setup
print(albatros.readline())
Comment on lines +26 to +32
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# this code will print the first four lines of the poem "L'albatros"
with open('albatros.txt','r') as poem:
for i in range(4):
print(poem.readline())
# this code will however create an error as we are already outside of the indented block and therefore no longer within the context that had been setup
print(albatros.readline())
# Printing the first four lines of the poem "L'albatros"
with open('albatros.txt', 'r') as poem:
for i in range(4):
print(poem.readline())

```

Output:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Output:
The above code produces the following output:


```md
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```md
```shell

Souvent, pour s'amuser, les hommes d'équipage

Prennent des albatros, vastes oiseaux des mers,

Qui suivent, indolents compagnons de voyage,

Le navire glissant sur les gouffres amers.
```

## Customized context managers for files

While `open()` is at the core of context managers working with files, it is still possible to implement context managers with additional capabilities, for example, to personalize files written using them. It can be done via two approaches: the **class-based approach**, and the **decorator-based approach**. Follow the links for more on [classes](https://www.codecademy.com/resources/docs/python/classes) and [decorators](https://www.codecademy.com/resources/docs/python/decorators).
Comment on lines +47 to +49
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Customized context managers for files
While `open()` is at the core of context managers working with files, it is still possible to implement context managers with additional capabilities, for example, to personalize files written using them. It can be done via two approaches: the **class-based approach**, and the **decorator-based approach**. Follow the links for more on [classes](https://www.codecademy.com/resources/docs/python/classes) and [decorators](https://www.codecademy.com/resources/docs/python/decorators).
## Customized Context Managers
While `open()` is at the core of using context managers with files, it is still possible to implement context managers with additional capabilities, e.g., personalizing files written using them. It can be done via two approaches:
- [Class](https://www.codecademy.com/resources/docs/python/classes)-based approach
- [Decorator](https://www.codecademy.com/resources/docs/python/decorators)-based approach


### Class-based approach

It rests on the three class methods `__init__()`, `__enter__()` and `__exit__()`. The context manager is invoked using the _with...as_ syntax and an instantiation of the class with needed parameters. The instantiation mobilizes a file thanks to the `__open__()` method and this file is in turn handled by the `__enter__()` method, allowing the operations indented in the _with_ block to be performed. Whatever the `__enter__()` method does a _return_ on can be then referred to in the indented block as the class instance created. Then the `__exit__()` method puts the final touch, closes the file, and handles any potential exception (_return True_ allows to close the file and go ahead in the script even if an exception occurs).

The below code exemplifies the class-based approach applied to a HR department sending automated yearly bonus notifications to employees. It's then quite easy to combine this context manager together with a [dictionary](https://www.codecademy.com/resources/docs/python/dictionaries) that contains all employees' records, loop through it, and have all the letters ready in no time.
Comment on lines +51 to +55
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Class-based approach
It rests on the three class methods `__init__()`, `__enter__()` and `__exit__()`. The context manager is invoked using the _with...as_ syntax and an instantiation of the class with needed parameters. The instantiation mobilizes a file thanks to the `__open__()` method and this file is in turn handled by the `__enter__()` method, allowing the operations indented in the _with_ block to be performed. Whatever the `__enter__()` method does a _return_ on can be then referred to in the indented block as the class instance created. Then the `__exit__()` method puts the final touch, closes the file, and handles any potential exception (_return True_ allows to close the file and go ahead in the script even if an exception occurs).
The below code exemplifies the class-based approach applied to a HR department sending automated yearly bonus notifications to employees. It's then quite easy to combine this context manager together with a [dictionary](https://www.codecademy.com/resources/docs/python/dictionaries) that contains all employees' records, loop through it, and have all the letters ready in no time.
### Class-Based Approach
Class-based approach rests on three class methods:
- `__init__()`
- `__enter__()`
- `__exit__()`
The context manager is invoked using the `_with...as_` syntax and an instantiation of the class with needed parameters. The instantiation mobilizes a file thanks to the `__open__()` method and the file is in turn handled by the `__enter__()` method, allowing the operations indented in the `_with_` block to be performed. Whatever the `__enter__()` method does a `_return_` on can then be referred to in the indented block. Lastly, the `__exit__()` method puts the final touch by closing the file and handling any potential exceptions.
> **Note:** `_return True_` allows the users to close the file and go ahead in the script even if an exception occurs.
The below code exemplifies the class-based approach applied to a HR department sending automated yearly bonus notifications to employees. Here, the context manager prepares all the letters by looping through a [dictionary](https://www.codecademy.com/resources/docs/python/dictionaries) that contains records for all employees:


```py
class bonus:
def __init__(self, employee_first,employee_id, salary, percentage):
self.first = employee_first
self.id = employee_id
self.salary = salary
self.pct = percentage
self.letter = open(str(self.id)+'_bonus_notice.txt','w')
self.thanks_message = open('thanks_message.txt', 'r')
self.conclusion = open('conclusion.txt','r')

def __enter__(self):
self.letter.write('Dear '+self.first +'!\n\n')
self.letter.write(self.thanks_message.read())
self.letter.write('\nYou will receive in addition to your December salary a yearly bonus that amounts to $'\
+str(round(self.salary*(self.pct/100)))+'.\n')

def __exit__(self,*exc):
self.letter.write(self.conclusion.read())
self.thanks_message.close()
self.conclusion.close()
self.letter.close()
return True

with bonus('John',3789,100000,5) as john_smith_bonus:
print('Letter printed!')
```

Result:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Result:
Here is the output:


```md
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```md
```shell

Dear John!

We value all our employees and are committed to their growth and well-being. We would like to thank you for your amazing work throughout this whole year.
You will receive in addition to your December salary a yearly bonus that amounts to $5000.
Again, allow us to thank you for all your efforts and to wish you all the best, for you and your family.

Sincerely yours,
Your HR department
```

### Decorator-based approach

In this approach, rather than a class is defined a [generator](https://www.codecademy.com/resources/docs/python/generators) function (i.e. a function performing a _yield_ and not a _return_). This function should be _decorated_ using `@contextmanager` from the built-in module `contextlib`:

```py
from contextlib import contextmanager
```

A decorator-based context manager is also using the user input in the form of parameters provided at the instantiation. It follows the syntax _try-except-finally_, _try_ being the part where the _yield_ statement is and the core operations are done, _except_ the exceptions handling part, and _finally_ the part where the resources are closed, essentially.

The below code shows an implementation of a decorator-based context manager thanks to which interview proposals are sent to pre-selected candidates. It is also possible (but not mandatory) to introduce some personalized elements in the indented block. If doing so this element will be placed just before the timeslot proposal.
Comment on lines +98 to +108
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Decorator-based approach
In this approach, rather than a class is defined a [generator](https://www.codecademy.com/resources/docs/python/generators) function (i.e. a function performing a _yield_ and not a _return_). This function should be _decorated_ using `@contextmanager` from the built-in module `contextlib`:
```py
from contextlib import contextmanager
```
A decorator-based context manager is also using the user input in the form of parameters provided at the instantiation. It follows the syntax _try-except-finally_, _try_ being the part where the _yield_ statement is and the core operations are done, _except_ the exceptions handling part, and _finally_ the part where the resources are closed, essentially.
The below code shows an implementation of a decorator-based context manager thanks to which interview proposals are sent to pre-selected candidates. It is also possible (but not mandatory) to introduce some personalized elements in the indented block. If doing so this element will be placed just before the timeslot proposal.
### Decorator-Based Approach
In decorator-based approach, a [generator](https://www.codecademy.com/resources/docs/python/generators) function (i.e., a function performing a `_yield_ ` and not a `_return_`) is defined rather than a class. This function is _decorated_ using `@contextmanager` from the built-in module `contextlib`:
```pseudo
from contextlib import contextmanager
```
A decorator-based context manager also uses the user input in the form of parameters provided at the instantiation. It follows the syntax `_try-except-finally_`, where `_try_` being the part where the `_yield_` statement is and the core operations are done, `_except_` being the part where the exceptions are handled and `_finally_` being the part where the resources are closed.
The below code shows an implementation of a decorator-based context manager thanks to which interview proposals are sent to pre-selected candidates. It is also possible (but not mandatory) to introduce some personalized elements in the indented block. Doing so places this element just before the timeslot proposal:


```py
@contextmanager
def interview_proposal(title_name, position, date, time):
proposal_letter = open(title_name+'_interview_proposal.txt','w')
try:
proposal_letter.write('Dear '+title_name + ',\n\nThanks a lot for being interested in working with us! \
We reviewed your application for the '+position+ ' role and we want to schedule a first visio interview with you.')
yield proposal_letter
except:
print('Exception handled!')
finally:
proposal_letter.write('Would you be available on '+date+ ' at '+time+'?\
\n\nWe look forward for hearing from you again! \nThe HR dept.')
proposal_letter.close()

with interview_proposal('Mr. Smith', 'Software Developer', 'Monday the 10th of June', '2 pm') as proposal_smith:
proposal_smith.write(' We are especially interested by your latest experience as a project leader \
for a wealth management software. ')
```

Result:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Result:
The output for the above code is as follows:


```md
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```md
```shell

Dear Mr. Smith,

Thanks a lot for being interested in working with us! We reviewed your application for the Software Developer role and we want to schedule a first visio interview with you. We are especially interested by your latest experience as a project leader for a wealth management software. Would you be available on Monday the 10th of June at 2 pm?

We look forward for hearing from you again!
The HR dept.
```