用 with 语句定义的变量可以在 with 块之外使用吗?

考虑下面的例子:

with open('a.txt') as f:
pass
# Is f supposed to be defined here?

我已经阅读了 with 语句的语言文档(2.7)以及 PEP-343,但据我所知,他们在这个问题上什么也没有说。

在 CPython 2.6.5中,f似乎是在 with-block 之外定义的,但是我不想依赖于可能发生变化的实现细节。

27440 次浏览

In case f is a file, it will be appear closed outside the with statement.

For example, this

f = 42
print f
with open('6432134.py') as f:
print f
print f

would print:

42
<open file '6432134.py', mode 'r' at 0x10050fb70>
<closed file '6432134.py', mode 'r' at 0x10050fb70>

You can find the details in PEP-0343 under the section Specification: The 'with' Statement. Python scope rules (which might be irritating) apply to f as well.

the with syntax:

with foo as bar:
baz()

is approximately sugar for:

try:
bar = foo.__enter__()
baz()
finally:
if foo.__exit__(*sys.exc_info()) and sys.exc_info():
raise

This is often useful. For example

import threading
with threading.Lock() as myLock:
frob()


with myLock:
frob_some_more()

the context manager may be of use more than once.

To answer Heikki's question in the comments: yes, this scoping behavior is part of the python language specification and will work on any and all compliant Pythons (which includes PyPy, Jython, and IronPython).

Yes, the context manager will be available outside the with statement and that is not implementation or version dependent. with statements do not create a new execution scope.