I am implementing my custom open()
function (let's call it myOpen()
). The task is, that I would like to be able to use this function also with with
statement (with myOpen(...) as myFile:
). As far as I know, open()
must return file object (TextIO
or BinaryIO
). But open()
in context of with
statement is not a function, but class, that implements __enter__
and __exit__
. Do you have any ideas, how to combine this two things together?
Thank you!

- 31
- 2
-
hope this helps https://stackoverflow.com/questions/53546824/multiple-ways-to-invoke-context-manager-in-python – Ade_1 Jun 04 '21 at 15:27
-
This post explains how to use `__enter__` and `__exit__` in a with expression: https://stackoverflow.com/questions/1984325/explaining-pythons-enter-and-exit – David Kaftan Jun 04 '21 at 15:38
-
When you use `with x() as y`, it is effectively assigning `y = x().__enter__()` – Peter Jun 04 '21 at 15:41
-
@Peter calling `with x() as y`, where `x()` is function, is giving me `AttributeError: __enter__` (Python 3.9.5) – wynxel Jun 04 '21 at 16:21
-
Ah nvm, I reread the question, the answer is no you can't combine a context manager and a function to do both things what once. What you can do however is design a class in a way where the logic is done in `__init__` and just have `def __enter__(self): return self`. That way you get the same result with or without using `with`. – Peter Jun 04 '21 at 19:54
2 Answers
Using a with
statement still returns a _io.x
class.
>>> type(open('_file_'))
<class '_io.TextIOWrapper'>
>>> with open('_file_') as o: print(type(o))
...
<class '_io.TextIOWrapper'>
The with
statement just assigns another variable for a block of code.
Example:
def five():
return 5
print(five()) # -> 5
print(type(five())) # -> int
with five() as x:
print(x) # -> 5
print(type(x)) # -> int
print(x) # -> 5
The with
statement is equivalent to
x = five()
print(x)
print(type(x))
or, for the FileIO
:
handle = open('_file_')
# do things with handle
-
Thank you, well, `with five() as x` gives me `AttributeError: __enter__` (python 3.9.5). Another question would be how can I handle `__exit__` in `myOpen()`? How can I close file descriprot in `myOpen()` function, when `with` statement exists? – wynxel Jun 04 '21 at 16:16
-
make a class with for your special filehandle, with `__enter__` and `__exit__` methods. – Jun 07 '21 at 12:56
Well, I figured out where was a problem. At the beginning I thought, that with
statement can be called only on class, which has those magic methods (__enter__
and __exit__
). So:
with class_that_has_those_methods as return_value_from_enter:
pass
But it works different. Expression after with
can be also function, but it has to return instance of class, which implements those magic methods. I think, that this is also the way, how python's open
works. It is function, which returns file object (more precisely wrapper):
>>> type(open)
<class 'builtin_function_or_method'>
>>> type(open('file', 'w'))
<class '_io.TextIOWrapper'>
and that file object implements those magic methods:
>>> a = open('file', 'w')
>>> dir(a)
[... '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', ...]
So to solve my original problem, myOpen()
has to be function, which returns file object, that has __enter__
and __exit__
methods.

- 31
- 2