Registry / ai-ml / pyobjc-framework-metal

pyobjc-framework-metal

JSON →
library12.2.2pypypiunverified

Wrappers for the “Metal” framework on macOS. PyObjC allows full-featured Cocoa applications to be written in pure Python, bridging Python and Objective-C. This specific package provides bindings for Apple's Metal framework, enabling GPU-accelerated computing and graphics. It is actively maintained with frequent updates tied to macOS SDK releases, currently at version 12.1.

pip install pyobjc-framework-metal
INSTALL
IMPORT
SIG · PYOBJC-FRAMEWORK-M
P
pyobjc-framework-metal
ai-mlpythonv12.2.2
Install
Import
Disk
Pass rate
0/ 10
Env Coverage0 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v? · pip install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
build_error
glibc
py 3.103.95 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Metal
import Metal
The Metal framework bindings are accessed directly through the 'Metal' package.

This quickstart demonstrates how to execute a basic Metal compute kernel using `pyobjc-framework-metal`. It initializes a Metal device, compiles a simple shader to add two arrays of numbers, sets up input/output buffers, dispatches the compute command, and reads the results back.

import Metal import objc import struct def run_metal_kernel(): # 1. Get the default Metal device device = Metal.MTLCreateSystemDefaultDevice() if device is None: print("Error: No Metal device found.") return print(f"Using Metal device: {device.name()}") # 2. Create a simple Metal shader (MSL) source # This kernel adds two numbers kernel_source = """ #include <metal_stdlib> kernel void add_numbers( device const float *inA [[buffer(0)]], device const float *inB [[buffer(1)]], device float *out [[buffer(2)]], uint id [[thread_position_in_grid]]) { out[id] = inA[id] + inB[id]; } """ # 3. Create a library from the source # Using newLibraryWithSource_options_error_ instead of newLibraryWithSource_options_error # as PyObjC usually appends '_' to methods with Objective-C error pointers. error_ptr = objc.nil library = device.newLibraryWithSource_options_error_(kernel_source, objc.nil, error_ptr) if library is None: # Check if error_ptr now points to an actual error object if error_ptr and error_ptr[0] is not objc.nil: # error_ptr is a C array of MTL_Error* in PyObjC error_obj = error_ptr[0] print(f"Failed to create Metal library: {error_obj.localizedDescription()}") else: print("Failed to create Metal library (unknown error).") return # 4. Get the kernel function function = library.newFunctionWithName_("add_numbers") if function is None: print("Error: Failed to find kernel function 'add_numbers'.") return # 5. Create a compute pipeline state pipeline_state = device.newComputePipelineStateWithFunction_error_(function, objc.nil) if pipeline_state is None: print("Error: Failed to create compute pipeline state.") return # 6. Prepare data data_size = 10 * struct.calcsize('f') # 10 floats input_a = [float(i) for i in range(10)] input_b = [float(i * 2) for i in range(10)] output_data = [0.0] * 10 # Create Metal buffers buffer_a = device.newBufferWithBytes_length_options_(bytes(struct.pack('f'*10, *input_a)), data_size, Metal.MTLResourceStorageModeManaged) buffer_b = device.newBufferWithBytes_length_options_(bytes(struct.pack('f'*10, *input_b)), data_size, Metal.MTLResourceStorageModeManaged) buffer_out = device.newBufferWithLength_options_(data_size, Metal.MTLResourceStorageModeManaged) # 7. Create a command queue command_queue = device.newCommandQueue_() if command_queue is None: print("Error: Failed to create command queue.") return # 8. Create a command buffer command_buffer = command_queue.commandBuffer_() # 9. Create a compute command encoder compute_encoder = command_buffer.computeCommandEncoder_() compute_encoder.setComputePipelineState_(pipeline_state) compute_encoder.setBuffer_offset_atIndex_(buffer_a, 0, 0) compute_encoder.setBuffer_offset_atIndex_(buffer_b, 0, 1) compute_encoder.setBuffer_offset_atIndex_(buffer_out, 0, 2) # 10. Dispatch threads grid_size = Metal.MTLSizeMake(10, 1, 1) thread_group_size = Metal.MTLSizeMake(min(10, pipeline_state.maxTotalThreadsPerThreadgroup()), 1, 1) compute_encoder.dispatchThreads_threadsPerThreadgroup_(grid_size, thread_group_size) compute_encoder.endEncoding_() # 11. Commit and wait for completion command_buffer.commit_() command_buffer.waitUntilCompleted_() # 12. Read results back to CPU (if using managed storage mode) buffer_out.didModifyRange_(Metal.NSMakeRange(0, data_size)) result_bytes = buffer_out.contents().tobytes() result = struct.unpack('f'*10, result_bytes) print("Input A:", input_a) print("Input B:", input_b) print("Output (A+B):", list(result)) expected_output = [input_a[i] + input_b[i] for i in range(10)] if all(abs(r - e) < 1e-5 for r, e in zip(result, expected_output)): print("✅ Output matches expected values.") else: print("❌ Output does not match expected values.") if __name__ == '__main__': run_metal_kernel()
Debug
Known issues
breakingPyObjC 12.0 dropped support for Python 3.9. PyObjC 11.0 dropped support for Python 3.8. Users should ensure they are on a supported Python version (>=3.10 for current 12.1).
fix
Upgrade Python to 3.10 or later, or use an older PyObjC version compatible with your Python environment.
affects: >=11.0
breakingPyObjC 11.1 updated its behavior for initializer methods (those in the 'init' family) to align with `clang`'s Automatic Reference Counting (ARC) documentation. These methods now correctly steal a reference to 'self' and return a new reference, which may change memory management expectations for code relying on previous PyObjC behavior.
fix
Review code interacting with Objective-C 'init' methods for potential reference counting issues, especially if manual memory management was assumed. Refer to Apple's ARC documentation.
affects: >=11.1
gotchaPyObjC 10.3 initially removed support for calling `__init__` when a user implements `__new__` in a Python subclass of an Objective-C class. While 10.3.1 reintroduced this capability for specific scenarios, developers should be aware that custom `__new__` implementations might interact unexpectedly with `__init__` due to underlying bridge changes.
fix
Carefully test custom `__new__` and `__init__` implementations in Python subclasses of Objective-C classes, especially when upgrading from versions prior to 10.3.
affects: >=10.3
gotchaStarting with PyObjC 12.1, Key-Value Observing (KVO) usage is automatically disabled for subclasses of `NSProxy` defined in Python. This change aims to prevent `SystemError` crashes that could occur in previous versions.
fix
Avoid relying on KVO for Python subclasses of `NSProxy`. If KVO-like behavior is needed, implement it manually within the Python class.
affects: >=12.1
gotchaOn macOS Sonoma (14) and later, the default path for `Metal.framework` has changed. This primarily affects low-level interactions that directly load the framework via `ctypes.CDLL` (e.g., `/System/Library/Frameworks/Metal.framework/Metal`), rather than through PyObjC's abstraction. Direct path lookups may fail.
fix
Rely on `pyobjc-framework-metal`'s abstraction for accessing Metal functionality. If direct `ctypes` loading is required, adapt paths to check `/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Metal.framework` or use `platform.mac_ver()` to determine the correct path dynamically.
affects: macOS 14+
gotchaPyObjC 11.0 introduced experimental support for Python's free-threading (PEP 703) in Python 3.13, but PyObjC 10.3 explicitly stated it did not support free-threading in Python 3.13. This is an evolving area, and stability with free-threading may vary across versions and require careful testing.
fix
If using Python 3.13+ with free-threading, test PyObjC interactions thoroughly and refer to the latest PyObjC documentation for compatibility and known issues.
affects: >=10.3
Upgrade
Version history
12.2.2latest on PyPI · released Aug 11, 2026
Audit
Dependencies
pyobjc-corerequiredProvides the core bridge between Python and Objective-C, essential for all PyObjC framework wrappers.
Agent activity
16 hits · last 30 days
node
12
OpenAI (training)
1
Resources
pyobjc-framework-metal — pip install pyobjc-framework-metal · libregistry