79613136

Date: 2025-05-08 20:42:12
Score: 4.5
Natty:
Report link

English
You're encountering this issue because you're trying to load a .pyd (native extension module) using a SourceLoader, which is intended for .py files (text). Native extensions like .pyd must be loaded using ExtensionFileLoader — otherwise, you’ll get DLL or encoding-related errors.

Assuming you dynamically created this structure:

/a/temp/dir/foo/
    __init__.py
    bar.pyd

You can correctly import the package and the .pyd module like this:

import sys
import importlib.util
import importlib.machinery
import os

def import_pyd_module(package_name, module_name, path_to_pyd, path_to_init):
    # Ensure package is imported first
    if package_name not in sys.modules:
        spec_pkg = importlib.util.spec_from_file_location(
            package_name,
            path_to_init,
            submodule_search_locations=[os.path.dirname(path_to_init)]
        )
        module_pkg = importlib.util.module_from_spec(spec_pkg)
        sys.modules[package_name] = module_pkg
        spec_pkg.loader.exec_module(module_pkg)

    # Load the compiled submodule
    fullname = f"{package_name}.{module_name}"
    loader = importlib.machinery.ExtensionFileLoader(fullname, path_to_pyd)
    spec = importlib.util.spec_from_file_location(fullname, path_to_pyd, loader=loader)
    module = importlib.util.module_from_spec(spec)
    sys.modules[fullname] = module
    spec.loader.exec_module(module)
    return module

Why Your Custom Loader Fails

Your MyLoader inherits from SourceLoader, which expects a .py file and calls get_data() expecting text. This cannot be used for .pyd files, which are binary and must be handled using the built-in ExtensionFileLoader.

If you want a custom import system with dynamic .pyd loading, you can still use a MetaPathFinder, but your loader must delegate to ExtensionFileLoader.

Usage:

mod = import_pyd_module(
    package_name="foo",
    module_name="bar",
    path_to_pyd="/a/temp/dir/foo/bar.pyd",
    path_to_init="/a/temp/dir/foo/__init__.py"
)

mod.some_method()

Spanish
Estás teniendo este problema porque intentas cargar un módulo compilado .pyd usando un SourceLoader, que está diseñado para archivos .py (texto fuente). Los archivos .pyd (extensiones nativas en Windows) deben cargarse usando ExtensionFileLoader, o de lo contrario recibirás errores como el de carga de DLL o problemas de codificación.

Supongamos que creaste dinámicamente la siguiente estructura:

/a/temp/dir/foo/
    __init__.py
    bar.pyd

Puedes importar correctamente el paquete y el módulo .pyd con el siguiente código:

import sys
import importlib.util
import importlib.machinery
import os

def importar_pyd_como_modulo(nombre_paquete, nombre_modulo, ruta_pyd, ruta_init):
    # Asegurar que el paquete esté importado primero
    if nombre_paquete not in sys.modules:
        spec_pkg = importlib.util.spec_from_file_location(
            nombre_paquete,
            ruta_init,
            submodule_search_locations=[os.path.dirname(ruta_init)]
        )
        modulo_pkg = importlib.util.module_from_spec(spec_pkg)
        sys.modules[nombre_paquete] = modulo_pkg
        spec_pkg.loader.exec_module(modulo_pkg)

    # Cargar el submódulo compilado
    nombre_completo = f"{nombre_paquete}.{nombre_modulo}"
    loader = importlib.machinery.ExtensionFileLoader(nombre_completo, ruta_pyd)
    spec = importlib.util.spec_from_file_location(nombre_completo, ruta_pyd, loader=loader)
    modulo = importlib.util.module_from_spec(spec)
    sys.modules[nombre_completo] = modulo
    spec.loader.exec_module(modulo)
    return modulo

Por qué falla tu MyLoader

Tu clase MyLoader hereda de SourceLoader, lo cual no sirve para archivos .pyd, porque espera archivos fuente .py y llama a get_data() esperando texto plano. Sin embargo, .pyd es binario, y debe manejarse con el loader nativo de extensiones: ExtensionFileLoader.

Si deseas implementar un sistema de carga personalizado, puedes seguir usando MetaPathFinder, pero el loader debe delegar a ExtensionFileLoader.

Reasons:
  • Blacklisted phrase (1): Está
  • Blacklisted phrase (1): está
  • Blacklisted phrase (1): porque
  • Blacklisted phrase (2): código
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Take36500