-1

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!

wynxel
  • 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 Answers2

0

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
0

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.

wynxel
  • 31
  • 2