-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py: __del__ special method not implemented for user-defined classes #1878
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You are correct that it does not work! In fact, the special method |
Include sphinx and recommonmark in docs/requirements.txt
Where did you got that from, i'm curious ... i guess you read too much javascript XD @dpgeorge, This should be implemented and active on unix port. Because when you load C++ classes via ffi wrappers ( ie from Python not from a C module ) you need to call dtor explicitely. use case: MicroPython uPanda3D bindings (WIP, desktop and web ) eg https://github.com/pmp-p/panda3d-interrogator/blob/master/tests/testpy.py#L149 should not have to be called manually |
will MICROPY_ENABLE_FINALISER fix that ? |
cPython docs: data model Well worth reading the section on tl;dr
|
Yes, same should be true for MicroPython: GC doesn't run on interpreter exit as far as I know, so if your object didn't get GC'd during running it
That adds support for calling the finaliser when an object gets garbage collected. So the aforementioned problem still exists. |
@stinos you made the point, that's because someone did forgot to cleanup on exit that |
Does this not just mean:
? |
i would not now i rarely use globals(), and i usually call del if don't want them to show up in inspection mode. on that snippet it's obvious you want a to survive interactive loop exit ( interpreter does not always exits there see "-i" invocation ) So i did put some C++ classes in locals() ( as in a function ) , run that function , call del on function, gc.collect() and ... |
I'm not sure |
At first glance, I would agree. And it's a bit annoying. |
reading #245 @dpgeorge @stinos c++ ffi handling needs python finalizers there's absolutely no need to force using precompiled C modules. wip use case: https://github.com/pmp-p/panda3d-interrogator/blob/master/build/upanda3d.py |
One more thought since this hasn't been mentioned explicitly: |
in my use case Of course i can use a context manager and even record state of global/locals and do mark and sweep on exit and also solve circular references ... but why ? better just do what ie thank you for not turning MicroPython in an obsolete javascript implementation ( FYI modern js is getting weakref and finalizers ) |
Are you specifically talking to me ? and what's the link with garbage collection ?
that's the sure way to crash with untracked (circular or not) references created within the context ( cf javascript ). so same as above thank you. eg:
|
@dpgeorge i'd really would like to know about I don't want to spend time generating plain C modules for interfacing C++ if not needed as i would not know how to use https://github.com/stinos/micropython-wrap for that. |
That even if you implement a destructor of a C++ object in
My point was rather that using a context manager will deterministically allow you to clean up resources in
Can you elaborate what exactly isn't clear, I'd be happy to clarify the Readme (but maybe better raise an issue in the repository itself in order not to derail this thread too much). |
I was curious what would be needed to implement this and unless I'm missing something it's a rather small change (with a performance impact though). In
to
and garbage collecting of user-defined classes will result in @dpgeorge you know if this is really all that's needed? If so this seems worth implementing conditionally. |
in that case scoping is of litle interest, only the finalizer getting called now or later or maybe never matters, but only gc can trigger that ( given circular ref can be solved ).
i'd prefer first a Python way to do that since MicroPython primary use is interpreting Python code maybe with the help of one specialized object type with native finalizer and callback handler:
ref : https://github.com/tc39/proposal-weakrefs
in case of FFI not working on emscripten or missing finalizer on MP the only way for me to complete my project ( a standalone wasm/wasi Panda3D runtime ) would be to build a C/C++ MicroPython module boxing C++ pointers , methods calls , enums , return types conversion to Python objects : just to get |
Not possible I think, there's no place where the core C code taking care of finalizers gets exposed to Python now.
Most of it I think yes but I don't yet have something for converting enums automaitcally for instance, and you do have to write the registration for each class/function, see the module.cpp file in the repository. Btw I don't think we ever had any problems using circular references or saw the need for weakref, which might be because we just wrap everything in a |
in continuation of cross posting #5106 and #4993 as ref
then define a RFC for a group finalizer and a MEP ie create a standard ? my proposal is : If people need The people who would need that are probably experienced anyway, so just give them 1 tool ( cheap of course but filling the void ). my code is clear because it's a working POC. Removing things to see what's really needed is a valid approach, but not moving even when javascript show you the way to do it (finally!) at low cost is not. The C line pasted |
Currently the only documentation and example is the code itself (which is fairly readable, given some C or similar background) and references to it here and on the forum.. The explanation for this one is fairly straightforward: m_new_obj_var_with_finaliser tells the allocator to create a new object and set a bit somewhere so when the object gets finalized, it gets scanned to see if it has |
That's i was missing : i thought having a del method on C object in a C module with a python instanciation would be autodetected just because finalizer are enabled. So if i get it right the C python "normal" object could create and hold a child with m_new_obj_var_with_finaliser without requiring anything out of the module ? that seems enough for a group finalizer. thx ! Sidenote i don't have much time for forum, i try to add bits to MP when i'm idle/compiling my primary target for my projects is still cpython on mobile/web so the lag in other subjects is not helping to crunch efficiently that time. https://forum.micropython.org/search.php?keywords=new_obj_var_with_finaliser => 0 |
Something like that yes. There's more than one way to achieve your proposal, apart from the example I gave with setting the flag one could also implement a type in C which takes a callback to allow calling an arbitrary function in it's finaliser, or have a C type which just has finaliser support and is meant to be subclassed in Python, or ... (note I edited my previous comment because I wrote it without checking the code, and it stated all C types use a finaliser by default but that's not true) |
For reference, here's an implementation of a type which calls an arbitrary function in it's finalizer
After adding this to modgc.c i.e. add
|
great, that looks exactly what i have in mind for cleaning up c/c++ pointer list. refing for the doc completion v923z/micropython-usermod#1 |
Just curious if there has been progress or update on this? I stumbled on it while trying to debug some code on an ESP32 running micropython 1.24.1. It took me some time with Google to figure out what was going on and then to locate the small mention in the documentation which led me to this issue. My biggest concern is that deleting an object & then calling gc.collect() will leave everything in the destroyed instance still in memory & still running (the class I've been working on uses a hardware timer & my del() shuts it down, although when I tried to destroy the object discovered that the timer was still running & still referencing variables which were part of the now destroyed object). |
If you need to make objects that free/stop/cleanup resources when no longer used, the best way to do it is with a context manager. This will ensure that things are cleaned up, even if an exception occurs. The second best way is to make a
|
Example:
According to this post #1802,
gc.collect()
should collect the object after thedel
and call the finaliser, but the finaliser is never called, any ideas?I know that a good programming practice is to assume that
__del__
may never be called, but hey, this still should work :)The text was updated successfully, but these errors were encountered: