Let's start with a common problem, file open:
try: open(‘xxx‘) do somethingexcept: do somethingfinally: f.close()
In fact, I personally see this on the Internet more than once, this is wrong.
The first is correct as follows:
try: f = open(‘xxx‘)except: ‘fail to open‘ exit(-1)try: do somethingexcept: do somethingfinally: f.close()
It's a lot of trouble, but the right way to do that is to write.
Why do we write it finally
because it prevents the program from throwing an exception and finally cannot close the file, but there is a prerequisite to closing the file if the file is already open.
In the first error code, if an exception occurs f=open(‘xxx’)
, such as when the file does not exist, it is immediately possible to know that execution f.close()
is meaningless. The corrected solution is the second piece of code.
All right, I'm going to start talking about with
grammar.
First we start with the following question about the try-finally
grammatical structure:
set things uptry: do somethingfinally: tear things down
This thing is a common structure, such as file Open, it means set things up
f=open(‘xxx‘)
tear things down
f.close()
. In such things as multi-threaded locks, resource requests, eventually there is a need to release. The Try…finally
structure ensures that tear things down
This section will always be executed, even if the above do something
work is not fully implemented.
That with
is, a control flow statement, and the if/for/while/try
like is a kind of, with
can be used to simplify try finally
the code, can look try finally
more clear.
A new "Context Management Protocol" is introduced here "context management protocol"
, which is implemented for a class definition __enter__
and __exit__
two functions.
with expresion as variable
The execution of the procedure is, first execute the __enter__
function, its return value will be assigned to as
the back variable
, want it to return what return what, as long as you know how to deal with it, if not write as variable
, the return value will be ignored.
The execution of the statement is then executed, regardless of the with-block
successful failure (such as an exception, error, setting sys.exit()
), and the with-block
function executes after completion __exit__
.
This process is actually equivalent to:
try: 执行 __enter__的内容 执行 with_block. finally: 执行 __exit__内容
Solution for the final python-dev
team. ( python 2.5
added with
syntax for the expression later)
class controlled_execution: def __enter__(self): set things up return thing def __exit__(self, type, value, traceback): tear things downwithas thing: do something
Just now, part of the code is encapsulated as a __enter__
function, and the cleanup code is encapsulated as a __exit__
function.
We can implement an example ourselves:
ImportSys class test: def __enter__(self):Print"Enter")return 1 def __exit__(Self,*args):Print"Exit")return True withTest () asT:print ("T is not the result of test (), it is __enter__ returned") Print ("T is 1, yes, it's {0}". Format (t))RaiseNameerror ("Hi There") Sys.exit () print ("Never Here")
Here, the python
syntax is used with-as
. When python
this sentence is executed, the function is called and the __enter__
value of the function return
is passed to the as
specified variable. After that, python
the following do something
block of statements is executed. Finally, no matter what exception occurs in the statement block, it will be executed at the time of departure __exit__
.
In addition, __exit__
in addition to tear things down
, you can also perform abnormal monitoring and processing, note the following several parameters. To skip an exception, you only need to return the function True
. The following sample code skips all of the TypeError
other exceptions and throws them normally.
def __exit__(self, type, value, traceback): return isinstance(value, TypeError)
In python2.5
and after the file
object has been written __enter__
and __exit__
functions, we can test it this way:
>>> f =Open("X.txt") >>> f<Open file ' X.txt ', mode' R ' at 0x00ae82f0>>>> f.__enter__ () <Open file ' X.txt ', mode' R ' at 0x00ae82f0>>>> F.Read(1)' X '>>> f.__exit__ (None, none, none) >>> F.Read(1) Traceback (most recent call Last): File"<stdin>", Line 1,inch<MODULE>VALUEERROR:I/O operationOn closed file
After that, we only need to do this if we want to open the file and make sure to close it last:
with open("x.txt"as f: data = f.read() dodata
If there are multiple items, we can write this:
withopen("x.txt"asopen(‘xxx.txt‘as f2: dowith f1,f2
As mentioned above, the __exit__
function can be handled partially, if we do not handle the exception in this function, he will throw normally, this time we can write ( python 2.7
and above version, the previous version reference use contextlib.nested
this library function):
try: withopen"a.txt"as f : do somethingexcept xxxError: doexception
In short, the with-as
expression greatly simplifies the work of each write finally
, which is very helpful to keep the code elegant.
Understand the with...as in Python ... Grammar