Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting 'WITH' statements in Python

It turns out that "with" is a funny word to search for on the internet.

Does anyone knows what the deal is with nesting with statements in python?
I've been tracking down a very slippery bug in a script I've been writing and I suspect that it's because I'm doing this:

with open(file1) as fsock1:
    with open(file2, 'a') as fsock2:
        fstring1 = fsock1.read()
        fstring2 = fsock2.read()

Python throws up when I try to read() from fsock2. Upon inspection in the debugger, this is because it thinks the file is empty. This wouldn't be worrisome except for the fact that running the exact same code in the debugging interperter not in a with statement shows me that the file is, in fact, quite full of text...

I'm going to proceed on the assumption that for now nesting with statements is a no-no, but if anyone who knows more has a different opinion, I'd love to hear it.

like image 700
Zefira Avatar asked Jan 02 '10 02:01

Zefira


People also ask

Can you have nested with statements in Python?

elif…else statement. This is called nesting in computer programming. Any number of these statements can be nested inside one another. Indentation is the only way to figure out the level of nesting.

What is the with statement in Python?

In Python, the with statement replaces a try-catch block with a concise shorthand. More importantly, it ensures closing resources right after processing them. A common example of using the with statement is reading or writing to a file. A function or class that supports the with statement is known as a context manager.

Can you stack if statements in Python?

It works that way in real life, and it works that way in Python. if statements can be nested within other if statements. This can actually be done indefinitely, and it doesn't matter where they are nested. You could put a second if within the initial if .

How do you run multiple if statements in Python?

Example. #!/usr/bin/python var = 100 if var < 200: print "Expression value is less than 200" if var == 150: print "Which is 150" elif var == 100: print "Which is 100" elif var == 50: print "Which is 50" elif var < 50: print "Expression value is less than 50" else: print "Could not find true expression" print "Good bye! ...


3 Answers

I found the solution in python's doc. You may want to have a look at this (Python 3) or this (Python 2)

If you are running python 2.7+ you can use it like this:

with open(file1) as fsock1, open(file2, 'a') as fsock2:
    fstring1 = fsock1.read()
    fstring2 = fsock2.read()

This way you avoid unnecessary indentation.

like image 144
R3ctor Avatar answered Oct 23 '22 06:10

R3ctor


AFAIK you can't read a file open with append mode 'a'.

like image 11
mechanical_meat Avatar answered Oct 23 '22 04:10

mechanical_meat


Upon inspection in the debugger, this is because it thinks the file is empty.

I think that happens because it can't actually read anything. Even if it could, when you append to a file, the seek pointer is moved to the end of the file in preparation for writing to occur.

These with statements work just fine for me:

with open(file1) as f:
    with open(file2, 'r') as g:   # Read, not append.
        fstring1 = f.read()
        fstring2 = g.read()

Note that use of contextlib.nested, as another poster suggested, is potentially fraught with peril here. Let's say you do this:

with contextlib.nested(open(file1, "wt"), open(file2)) as (f_out, f_in):
   ...

The context managers here get created one at a time. That means that if the opening of file2 fails (say, because it doesn't exist), then you won't be able to properly finalize file1 and you'll have to leave it up to the garbage collector. That's potentially a Very Bad Thing.

like image 8
John Feminella Avatar answered Oct 23 '22 04:10

John Feminella