Deallocating objective-C class
Describe the bug
When running a piece of code, I get this print:
Deallocating objective-C class VNRecognizeTextRequest
It seems like this is unexpected: https://github.com/ronaldoussoren/pyobjc/blob/b4efea53d01d5715de985a4f28758d0c80a64f76/pyobjc-core/Modules/objc/objc-class.m#L1182-L1188
It seems like this only happens if I do a local import in a function:
def foo():
import Cocoa, Vision, objc
I can try to come up with a reproducer if requested.
Platform information
PyObjC from conda-forge and from pip
❯ pixi list | grep objc
pyobjc-core 10.3.1 py312hbb55c70_0 479.6 KiB conda pyobjc-core-10.3.1-py312hbb55c70_0.conda
pyobjc-framework-cocoa 10.3.1 py312hbb55c70_0 370.5 KiB conda pyobjc-framework-cocoa-10.3.1-py312hbb55c70_0.conda
pyobjc_framework_coreml 10.3.1 111.8 KiB pypi pyobjc_framework_coreml-10.3.1-cp36-abi3-macosx_11_0_universal2.http.whl
pyobjc_framework_quartz 10.3.1 1.6 MiB pypi pyobjc_framework_quartz-10.3.1-cp312-cp312-macosx_10_9_universal2.http.whl
pyobjc_framework_vision 10.3.1 156.7 KiB pypi pyobjc_framework_vision-10.3.1-cp36-abi3-macosx_11_0_universal2.http.whl
macOS version: 14.5 (23F79)
To Reproduce
Not sure how to reproduce in an isolated piece of code (haven't tried).
Expected behavior
Not sure
A reproducer would be nice because this should not happen.
Can you reproduce this in your code when using PyObjC 10.3.0?
Reproducer:
from concurrent.futures import ThreadPoolExecutor
def foobar():
import Vision
x = Vision.VNRecognizedTextObservation
with ThreadPoolExecutor() as pool:
for _ in range(2):
pool.submit(foobar)
Thanks for the reproducer.
I'm starting to understand what going on here, but do not have a solution at this point. There is a race condition in the ObjC parts of pyobjc-core in updating some core data structures (caused be reentering the interpreter in a block of my code that thinks its protected from reentrancy by the GIL).
BTW. Your timing in reporting this is spot on, I'm working on making PyObjC compatible with the free threaded build of Python 3.13 and this would have been a real head scratcher if I'd found this while testing the free threaded build...
I've committed a fix for this in the master branch, will backport this to the in current stable branch as well.
As a workaround: make sure that classes are imported only on a single thread, such as by importing classes when the module/script is loaded instead of in a nested function.
Thanks for the prompt fix!