Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a "with" statement be used conditionally?

I have a Python function of roughly the following structure, that computes some results and writes them to a file:

results = []
with open(filename, "w") as output:
    for item in items:
        result = compute_stuff(item)
        write_result(item, result, output)
        results.append(result)
return results

Now I don't always want to write the results to file - sometimes I only want to compute them and have them returned. Making "write_result" conditional is easy, but is there also a way to make the file creation in the "with" statement condition-dependent? (I know I could handle opening and closing of the file explicitly, but I would incur the "try/finally" overhead that the "with" statement was created to avoid.)

Is there an elegant solution for this?

Edited to add: I may have oversimplified the example. Instead of writing to an arbitrary file, I'm using matplotlib.backends.backend_pdf.PdfPages (link), and adding a plot (new page in the PDF) in every step. In particular, that means I cannot re-open the PDF file with PdfPages, because it would be overwritten.

like image 852
Hendrik Avatar asked Mar 06 '14 13:03

Hendrik


People also ask

What are the conditional statements used in Python?

Python has 3 key Conditional Statements that you should know: if statement. if-else statement. if-elif-else ladder.

Which of the following is not the conditional statement in Python?

25. Which of the following is not used as conditional statement in Python? Explanation: Python does not have a switch or case statement like other programming languages.

Does Python support conditional statements?

In a Python program, the if statement is how you perform this sort of decision-making. It allows for conditional execution of a statement or group of statements based on the value of an expression.


2 Answers

You can write your own context manager function:

class Dummysink(object):
    def write(self, data):
        pass # ignore the data
    def __enter__(self): return self
    def __exit__(*x): pass

def datasink(filename):
    if filename:
        return open(filename, "w")
    else:
        return Dummysink()

...

results = []
with datasink(filename) as output:
    for item in items:
        result = compute_stuff(item)
        write_result(item, result, output)
        results.append(result)
return results
like image 94
glglgl Avatar answered Oct 13 '22 00:10

glglgl


Use a helper function to wrap the real open() which either calls the real open() or which returns an object that has the methods write(), flush() and close():

class MockFile(object):
    def write(self, data): pass
    def flush(self): pass
    def close(self): pass

def optionalWrite(filename, mode):
    if writeForRead: # <--- Your condition here
        return open(filename, mode)

    return MockFile()

with optionalWrite as output:
    ...
like image 22
Aaron Digulla Avatar answered Oct 12 '22 23:10

Aaron Digulla