def __init__(self, number):
self.number = number
fh = open(r"Desktop\Now.txt", 'a')
fh.write(f"New object having number {self.number} has been created\n")
fh.close()
def __del__(self):
fh = open(r"Desktop\Now.txt", 'a')
fh.write(f"Object number {self.number} destroyed")
fh.close()
Iām not an expert, but I think the open builtin is being deleted before the instances. Have a look at the warning in the documentation for __del__ here:
This works if you unbind the variables t1, t2 and t3 before interpreter shutdown:
class Test:
def __init__(self, number):
self.number = number
fh = open("/home/jean/tmp/now.txt", 'a')
fh.write(f"New object having number {self.number} has been created\n")
fh.close()
def __del__(self):
fh = open(r"/home/jean/tmp/now.txt", 'a')
fh.write(f"Object number {self.number} destroyed")
fh.close()
t1 = Test(1)
t2 = Test(2)
t3 = Test(3)
del t1
del t2
del t3
Hey thanks for replyingā¦In the above caseā¦you explicitly called the destructor method by deleting the reference variablesā¦I am still not clear why this works but still it is helpfullā¦I will let you know if I make any further progress on this!!
The __del__ method is only called after the object has no more
references. In CPython (the common implementation) objects are reference
counted, and __del__ is called as soon as the last reference
disappears. In other implementations that might happen later.
Jeanās suggestion doesnot call the __del__ method. Running:
del t1
does not call t1.del. Instead, it removes the reference to the
object you got from Test(1) stored in āt1ā. Because that is the only
reference, in CPython the __del__ method gets called at that point.
Jeanās point is that if you do not remove the reference yourself, it
gets removed at programme shutdown. The order in which those references
are removed is not specified - all sorts of things may be gone by that
point.
However, I do not expect that the open() function will be gone.
Instead, I suspect that self.number may be gone. At programme
shutdown, the order in which objects are destroyed is not specified.
If you had posted the error message and traceback you received we would
have a better idea. It is always important to include this information.
and there is no error when deleting those instances either:
>>> del t1
>>> del t2
>>> del t3
>>>
and the file is written to:
>>> with open(r"Desktop\Now.txt") as f:
... print(f.read())
...
New object having number 1 has been created
New object having number 2 has been created
New object having number 3 has been created
Object number 1 destroyedObject number 2 destroyedObject number 3 destroyed
So to answer your questions:
you can use open inside a __del__ method;
I have no idea why your code raises an exception, it works for me.
Are you running under a IDE or other non-standard environment? I guess
you are using Windows (from the use of a backslash in the file path) but
can you explain where and how you are getting an exception, and what the
exception is, please?
On further investigation, I find that I can cause an error by running
the code as a stand-alone script. Steps to reproduce the error:
save the code in a file, ādeltest.pyā
run python3 deltest.py
The error seems to be occurring during interpreter shutdown:
Exception ignored in: <function Test.__del__ at 0x7f955ad07f80>
Traceback (most recent call last):
File "deltest.py", line 11, in __del__
NameError: name 'open' is not defined
Exception ignored in: <function Test.__del__ at 0x7f955ad07f80>
Traceback (most recent call last):
File "deltest.py", line 11, in __del__
NameError: name 'open' is not defined
Exception ignored in: <function Test.__del__ at 0x7f955ad07f80>
Traceback (most recent call last):
File "deltest.py", line 11, in __del__
NameError: name 'open' is not defined
This seems very oddā¦ it looks like the builtins are being garbage
collected before other objects. I didnāt think that was possible. I
thought that the builtins were garbage collected last, not first.
I have tested this under both 3.9 and 3.7, and after making a few minor
changes to get the code to compile, under 3.5, and it fails every time.
But it works without error under Python 2.7.
Can somebody convince me that this is not a bug in the shutdown
procedure? Given that Python supports object finalisers, __del__, I
would expect that something as simple as this one should work even at
interpreter shutdown. Thereās no complicated issues with cycles, or
threads, I would have expected something simple and straightforward:
delete the module globals t1, t2, t3
which runs their finalisers
only after that, delete builtins
but it seems that builtins is being deleted first. Why?
On further investigation, I find that I can cause an error by running
the code as a stand-alone script. Steps to reproduce the error:
save the code in a file, ādeltest.pyā
run python3 deltest.py
The error seems to be occurring during interpreter shutdown:
Exception ignored in: <function Test.__del__ at 0x7f955ad07f80>
Traceback (most recent call last):
File "deltest.py", line 11, in __del__
NameError: name 'open' is not defined
[ā¦]
This seems very odd... it looks like the builtins are being garbage
collected before other objects. I didn't think that was possible. I
thought that the builtins were garbage collected last, not first.
I thought it impossible too!
I have tested this under both 3.9 and 3.7, and after making a few minor
changes to get the code to compile, under 3.5, and it fails every time.
But it works without error under Python 2.7.
Can somebody convince me that this is not a bug in the shutdown
procedure? Given that Python supports object finalisers, __del__, I
would expect that something as simple as this one should work even at
interpreter shutdown. Thereās no complicated issues with cycles, or
threads, I would have expected something simple and straightforward:
delete the module globals t1, t2, t3
which runs their finalisers
only after that, delete builtins
but it seems that builtins is being deleted first. Why?
Because ābā comes before ā_ā? Insertion ordered modules dicts? An
accident? A ruthless ādonāt let users dependend on the cleanup orderā?
But yeah, Iād have thought a little nuance in interpreter shutdown might
leading to del code working more often than not. Whther thatās a
good thing is debatable. (Not a fan of bugs which show up late eg after
deployment).
Yesā¦I meant the same when I said that he was explicitly calling the del methodā¦moreover,I knew that at the end of script all objects are made availabe for garbage collectionā¦hence I tried this example at homeā¦but it didnt workā¦next time I post a question,I will post the error message I get along with my questionā¦Thanks for helping.