问题
From Python's source code of open, I think open
is just a normal function.
Why can we use it like below?
with open('what_are_context_managers.txt', 'r') as infile:
for line in infile:
print('> {}'.format(line))
Since is neither implements __enter__
nor __exit__
, nor uses contextlib.contextmanager
decorator.
回答1:
You are not using the open
function as a context manager. It is the result of the open(...)
call expression that is the context manager. open()
returns a file object, and it is that object that has __enter__
and __exit__
methods; see the io.IOBase documentation:
IOBase is also a context manager and therefore supports the with statement.
You can read the with
statement like this:
_context_manager = open('what_are_context_managers.txt', 'r')
with _context_manager as infile:
Note that it is the return value of _context_manager.__enter__()
that ends up being assigned to infile
here. For file objects, file.__enter__()
returns self
, so you can get access to the same object that way.
As a side-note; you got the wrong open()
function. The actual definition of the open()
built-in is an alias for io.open(), see the _iomodule.c source code. The alias is set in initstdio() in pylifecycle.c (where io.OpenWrapper
is itself an alias for _io.open). And yes, the documentation states the alias points the other way for end-user ease.
来源:https://stackoverflow.com/questions/43757161/why-can-you-use-open-as-context-manager