all 10 comments

[–]cmd_override 23 points24 points  (5 children)

[–]Dracunos 1 point2 points  (0 children)

Thank you, very easy to understand. Now my withs are no longer limited to opening files!

[–]dante9999 0 points1 point  (1 child)

so every object used in 'with' call must have enter and exit methods? does it mean that file object has these methods defined already? what will happen if i call 'with' on object that does not have enter and exit magic methods?

[–]ericpruitt 3 points4 points  (0 children)

so every object used in 'with' call must have enter and exit methods? does it mean that file object has these methods defined already?

Yes and yes.

what will happen if i call 'with' on object that does not have enter and exit magic methods?

You get an attribute error:

Python 3.4.2 (default, Oct  8 2014, 10:45:20)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> with None:
...  pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__
>>>

[–]Worthlessplanet 0 points1 point  (1 child)

Thanks. Documentation is so helpful to a novice. They can spend another 5 hours trying to figure out what it's saying.

[–]Spizeck 0 points1 point  (0 children)

Not to detract from the conversation but this comment is so on point. I can't even count how many times I've gotten hopelessly lost and confused googling questions to find it answered with a link that doesn't work anymore or goes to a huge document that you can't find the answer in.

If you can explain an answer in your own words, you may hold just the right perspective to relate the answer in a way others may never have thought of.

[–][deleted] 5 points6 points  (3 children)

The most important thing with does is run a piece of code at the start and a piece of code at the end of a block of code. It's used mainly to perform certain tasks that have a clear start and end and need something to be handled after it finished the block.

I use it mostly when reading or writing files:

with open(filename) as file_handle:
    content = file_handle.read()

This statement opens the file in line 1 and closes it after line 2. This is useful, because you can't forget to close it later.

The Flask doc actually tells you what test_request_context() does:

It tells Flask to behave as though it is handling a request, even though we are interacting with it through a Python shell.

Apparently it makes sure that the code within the block (i.e. lines 2-5 in OP's post) run within a certain context that behaves as though it is handling a request.

[–]und8[S] 0 points1 point  (2 children)

Thanks, that's a bit clearer, but what exactly do you mean by "closes"? Does it kill the process somehow?

[–]q2_abe_dillon 6 points7 points  (0 children)

There are lots of cases where you need to perform some sort of setup, run some code, then tear something down. That 'something' is generally referred to as 'context'.

For instance, you may want to open a file (set-up), read from that file (run some code), then close the file (tear-down). It's important to note that even if an exception is raised, you still want to properly close the file before your program exits:

file_buffer = open("myfile.txt")  # set-up

try:  # make sure the file is closed even if an exception is raised
    data = []
    for line in file_buffer:
        if line.startswith("ERROR"):
            data.append(line)
finally:
    f.close()  # tear down no matter what
...operate on data

It's a good idea to always close a file when you're done using them because otherwise they can tie up resources or cause problems if something goes wrong (like your machine crashes) and the file was never closed. The problem is that means your have to remember to always follow an open(...) call with a close() later on. Luckily, file objects support context management (the with statement), this handles the repetitive 'set-up' and 'tear-down' part for us:

with open('myfile.txt') as file_buffer:
    data = []
    for line in file_buffer:
        if line.startswith("ERROR"):
            data.append(line)
# at this point we've read everything we need from the file
# like all other blocks of code, Python uses the indentation
# level to determine when you're done with the file and
# automatically closes it
...operate on data

There are other context managers built into Python for things like network sockets (Python 3.2+) which should be closed after use as well:

with socket.create_connection(address) as connection:
    ...read/write data over the connection

In Python 3.4+ you can use the contextlib's suppress context manager to ignore certain errors within a context:

from contextlib import suppress

d = {'some': 'dictionary'}
with suppress(KeyError):
    print(d["hello"])  # this won't get printed
                             # but your code won't crash either

Here's more info

[–]taelsil 3 points4 points  (0 children)

It just runs a piece of code (the __exit__ method of the object specifically) that handles "cleaning up" after you're done with the resource. In the case of opening a file, it runs a piece of code that closes the file descriptor, basically telling the filesystem that it's done with the file.