Mailing List Archive

Context without manager
Hi all,

I apologize in advance for the "foggy"
question, but I've myself unclear ideas.

Anyway...

Python has "context manager".
For example, the "open()" class can be
simply used as follow:

with open(...) as fp:
fp.do_something()

On the other hand, it is also possible to do:

fp = open()
fp.do_something()
fp.close()

Now, if we want to use "open()" in a class,
it would be possible to apply the second
variant, with "self.fp = open()" in "__init__(...)",
"self.fp.close()" maybe in "__del__(...)" and having
few methods doing this and that with the "self.fp".

Apparently, the "with" context manager is not usable
in classes, at least not with __init__() & co.

It seems there are classes ("gradio.Blocks()", for
example) which are *only* usable with context manager.

I found more...

One way to do the same as in "open()" is:

def __init__(...):
fp = open(...)
fp.__enter__()
...
def __del__(...):
fp.__exit__()
fp.close()

This works, but it seems quite ugly.
I could not find any other way, in case the
class do only support context manager.

Question: is there any other way to use a
context manager only object within a class,
with methods accessing the object?

Or any other solution to the same situation?

Thanks a lot in advance.

P.S.: currently gmail posts are deleted, due
to excessive spam, so I'll not see any reply
coming from this family of addresses.

bye,

--

piergiorgio
--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
Piergiorgio Sartor wrote at 2023-11-25 22:15 +0100:
> ...
>Apparently, the "with" context manager is not usable
>in classes, at least not with __init__() & co.

You can use `with` in classes -- with any context manager.
However, you would usually not use `with` with a file you have opened
in `__init__`.

If a class defines `__enter__` and `__exit__` (i.e.
the "cntext manager protocol"), then its instances
can be used with the `with` statement.

The important use case for a context manager is the
situation:
set up a context (--> method `__enter__`)
perform some operations in this context (--> body of `with` statement)
tear down the context (--> method `__exit__`).
If you do not have this case (e.g. usually if you open the file
in a class's `__init__`), you do not use a context manager.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
On 26/11/2023 18.50, Dieter Maurer wrote:
> Piergiorgio Sartor wrote at 2023-11-25 22:15 +0100:
>> ...
>> Apparently, the "with" context manager is not usable
>> in classes, at least not with __init__() & co.
>
> You can use `with` in classes -- with any context manager.
> However, you would usually not use `with` with a file you have opened
> in `__init__`.
>
> If a class defines `__enter__` and `__exit__` (i.e.
> the "cntext manager protocol"), then its instances
> can be used with the `with` statement.
>
> The important use case for a context manager is the
> situation:
> set up a context (--> method `__enter__`)
> perform some operations in this context (--> body of `with` statement)
> tear down the context (--> method `__exit__`).
> If you do not have this case (e.g. usually if you open the file
> in a class's `__init__`), you do not use a context manager.

Very clear, but what if the class is *not* "open()",
but something else _requiring_ using "with"?
How to do this in a "__init__()" of a class?

In other words, what if "open()" could *only* be used
with "with" and not just by assigning "fp = open()"?

The problem is I've some SDK of some device which
provides context manager *only* classes.

I *cannot* do:

device = device_open(...)
device.do_something()
device.close()

I *must* do:

with device_open() as device:
device.do_something()

Nevertheless, I _need_ to have a class
where the device is opened in the __init__()
and used in some methods.

Any ideas?

bye,

--

piergiorgio

--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
On 2023-11-26, Dieter Maurer via Python-list <python-list@python.org> wrote:

> If you do not have this case (e.g. usually if you open the file
> in a class's `__init__`), you do not use a context manager.

He knows that. The OP wrote that he wants to use <something> that can
_only_ be used by a context manager, but he wants that usage to be
spread over various methods of a class he's writing. So he's asking
how to fool that <something> into working when he's not using a
context manager.

--
Grnat




--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
On 2023-11-27, Grant Edwards via Python-list <python-list@python.org> wrote:
> On 2023-11-26, Dieter Maurer via Python-list <python-list@python.org> wrote:
>
>> If you do not have this case (e.g. usually if you open the file
>> in a class's `__init__`), you do not use a context manager.
>
> He knows that. The OP wrote that he wants to use <something> that can
> _only_ be used by a context manager, but he wants that usage to be
> spread over various methods of a class he's writing. So he's asking
> how to fool that <something> into working when he's not using a
> context manager.

I should probably have written "how to fool that <something> into
working when he's not using a 'with' statement"

--
Grant
--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
On 27/11/23 9:03 am, Stefan Ram wrote:
> Above, "have" is followed by another verb in "have been",
> so it should be eligible for a contraction there!

Yes, "been" is the past participle of 'to be", so "I've been" is
fine.

--
Greg

--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
On 27/11/23 5:03 pm, Grant Edwards wrote:
> I should probably have written "how to fool that <something> into
> working when he's not using a 'with' statement"

It should be possible to run the context protocol yourself.
Something like (warning, untested):

class MyDeviceWrapper:

def __init__(self):
self.cm = device_open()
self.device = self.cm.__enter__()

# Other methods here for doing things with
# self.device

def close(self):
self.cm.__exit__(None, None, None)

--
Greg

--
https://mail.python.org/mailman/listinfo/python-list
Re: Context without manager [ In reply to ]
?Read the Fine context manager documentation.
What “with with_expression as var” does is effectively:

ob = with_expression
var = ob.__enter__()

And then at the end of the with, does a
ob.__exit__()

(With some parameters to __exit__, that could just be None, None, None for the simplest case).

Note, YOUR program must now make sure that the __exit__ function is called, and handle any exceptions that got thrown, and that ob and var are put somewhere you can access them at that later time.


> On Nov 27, 2023, at 12:24?PM, Piergiorgio Sartor via Python-list <python-list@python.org> wrote:
>
> ?On 26/11/2023 18.50, Dieter Maurer wrote:
>> Piergiorgio Sartor wrote at 2023-11-25 22:15 +0100:
>>> ...
>>> Apparently, the "with" context manager is not usable
>>> in classes, at least not with __init__() & co.
>> You can use `with` in classes -- with any context manager.
>> However, you would usually not use `with` with a file you have opened
>> in `__init__`.
>> If a class defines `__enter__` and `__exit__` (i.e.
>> the "cntext manager protocol"), then its instances
>> can be used with the `with` statement.
>> The important use case for a context manager is the
>> situation:
>> set up a context (--> method `__enter__`)
>> perform some operations in this context (--> body of `with` statement)
>> tear down the context (--> method `__exit__`).
>> If you do not have this case (e.g. usually if you open the file
>> in a class's `__init__`), you do not use a context manager.
>
> Very clear, but what if the class is *not* "open()",
> but something else _requiring_ using "with"?
> How to do this in a "__init__()" of a class?
>
> In other words, what if "open()" could *only* be used
> with "with" and not just by assigning "fp = open()"?
>
> The problem is I've some SDK of some device which
> provides context manager *only* classes.
>
> I *cannot* do:
>
> device = device_open(...)
> device.do_something()
> device.close()
>
> I *must* do:
>
> with device_open() as device:
> device.do_something()
>
> Nevertheless, I _need_ to have a class
> where the device is opened in the __init__()
> and used in some methods.
>
> Any ideas?
>
> bye,
>
> --
>
> piergiorgio
>
> --
> https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
RE: Context without manager [ In reply to ]
> I *must* do:
>
> with device_open() as device:
> device.do_something()
>
> Nevertheless, I _need_ to have a class
> where the device is opened in the __init__()
> and used in some methods.
>
> Any ideas?

Perhaps take a look at contextlib.ExitStack and see if you can do something with it.

(Below is not tested)

import contextlib
class myClass:
def __init__(self):
self._exitStack = contextlib.ExitStack()
device = self._exitStack.enter_context(device_open(...))
def __del__(self):
self._exitStack.close()
--
https://mail.python.org/mailman/listinfo/python-list