pythonwith-statement

How to check if an object is created with `with` statement?


I would like to ensure that the class is only instantiated within a "with" statement.

i.e. this one is ok:

with X() as x:
 ...

and this is not:

x = X()

How can I ensure such functionality?


Solution

  • All answers so far do not provide what (I think) OP wants directly.
    (I think) OP wants something like this:

    >>> with X() as x:
     ...  # ok
    
    >>> x = X()  # ERROR
    
    Traceback (most recent call last):
      File "run.py", line 18, in <module>
        x = X()
      File "run.py", line 9, in __init__
        raise Exception("Should only be used with `with`")
    Exception: Should only be used with `with`
    

    This is what I come up with, it may not be very robust, but I think it's closest to OP's intention.

    import inspect
    import linecache
    
    class X():
        
        def __init__(self):
            if not linecache.getline(__file__,
                inspect.getlineno(inspect.currentframe().f_back)).lstrip(
            ).startswith("with "):
                raise Exception("Should only be used with `with`")
    
        def __enter__(self):
            return self
        
        def __exit__(self, *exc_info):
            pass
    

    This will give the exact same output as I showed above as long as with is in the same line with X() when using context manager.