687

What is the python keyword "with" used for?

Example from: http://docs.python.org/tutorial/inputoutput.html

>>> with open('/tmp/workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True
S.Lott
  • 384,516
  • 81
  • 508
  • 779
MikeN
  • 45,039
  • 49
  • 151
  • 227
  • It’s handy when you have two related operations which you’d like to execute as a pair and you need the execution of both of them to be guaranteed no matter how the nested code in between them might exit. See an example here: https://preshing.com/20110920/the-python-with-statement-by-example/ – aderchox Apr 03 '20 at 17:16
  • 1
    Since I think that Fredrik Lundh's explanation is still one of the best, and since effbot.org is now "on hiatus" -- here's one of the snapshots from archive.org: [http://effbot.org/zone/python-with-statement.htm](http://web.archive.org/web/20180310054708/http://effbot.org/zone/python-with-statement.htm) – ジョージ Jul 01 '21 at 08:03

2 Answers2

623

In python the with keyword is used when working with unmanaged resources (like file streams). It is similar to the using statement in VB.NET and C#. It allows you to ensure that a resource is "cleaned up" when the code that uses it finishes running, even if exceptions are thrown. It provides 'syntactic sugar' for try/finally blocks.

From Python Docs:

The with statement clarifies code that previously would use try...finally blocks to ensure that clean-up code is executed.

The with statement is a control-flow structure whose basic structure is:

with expression [as variable]:
    with-block

The expression is evaluated, and it should result in an object that supports the context management protocol (that is, has __enter__() and __exit__() methods).

Update fixed VB callout per Scott Wisniewski's comment. I was indeed confusing with with using.

Chris Schmitz
  • 20,160
  • 30
  • 81
  • 137
Rob Allen
  • 17,381
  • 5
  • 52
  • 70
  • 9
    What methods are used to close the open resource? What if I made my own file system object that had its own special open/close methods, would the "with" keyword work with those? Or will "with" only work with the built-in Python resource types? – MikeN Sep 03 '09 at 12:43
  • 24
    In Python it looks like the custom object would have to implement (or inherit from something which implements) the `__enter__` and `__exit__` methods. With IronPython (python on .Net) you can implement from IDisposable and that will cover it. Not sure what is the best way in pure Python or other frameworks. – Rob Allen Sep 03 '09 at 14:10
  • 4
    FYI: this is confusing the "using" statement in VB.NET, which behaves like the "with" block in python, with the "with" statement in VB which is completely different. See the following: http://msdn.microsoft.com/en-us/library/htd05whh.aspx and http://msdn.microsoft.com/en-us/library/wc500chb(v=vs.110).aspx – Scott Wisniewski Dec 01 '13 at 20:08
481

Explanation from the Preshing on Programming blog:

It’s handy when you have two related operations which you’d like to execute as a pair or more, with a block of code in between. The classic example is opening a file, manipulating the file, then closing it:

 with open('output.txt', 'w') as f:
     f.write('Hi there!')

The above with statement will automatically close the file after the nested block of code. (Continue reading to see exactly how the close occurs.) The advantage of using a with statement is that it is guaranteed to close the file no matter how the nested block exits. If an exception occurs before the end of the block, it will close the file before the exception is caught by an outer exception handler. If the nested block were to contain a return statement, or a continue or break statement, the with statement would automatically close the file in those cases, too.

Rob Kwasowski
  • 2,690
  • 3
  • 13
  • 32
user1559873
  • 6,650
  • 8
  • 25
  • 28
  • 1
    I want to add an additional answer for the use of with in python, not related to opening or close file : def test_new_user_invalid_email(self): """Test creating user with no email raises error""" with self.assertRaises(ValueError): get_user_model().objects.create_user(None, 'pass@word') – joe-khoa Feb 16 '21 at 15:50