Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

pythonnet 3.0.x fails to expose types from .NET 8 assemblies (CoreCLR), works with .NET 9 #2595

Open
@drache42

Description

@drache42

Environment:

  • Python: 3.12.x
  • pythonnet: 3.0.3, 3.0.5 (and other 3.0.x versions)
  • clr-loader: 0.2.6 (also tested with 0.2.7.post0)
  • .NET Runtimes Tested:
    • .NET 8 (e.g., 8.0.16) -Fails
    • .NET 9 (e.g., 9.0.5) -Works
  • OS: Windows 10/11 (primarily tested on Windows)

Problem:
When usingpythonnet 3.0.x with Python 3.12 to interact with .NET 8 assemblies via CoreCLR,pythonnet successfully loads the .NET 8 runtime and the target assemblies into the AppDomain. However, it fails to properly expose the .NET types to the Python environment. This results inAttributeError when trying to access types directly from an imported namespace, orImportError when a Python module within a package attempts to import these .NET types.

The same operations succeed when the .NET assembly is compiled for .NET 9 and the .NET 9 runtime is used with the samepythonnet version.

Observed Behavior (.NET 8):

  1. .NET 8 CoreCLR is loaded (confirmed viaSystem.Runtime.InteropServices.RuntimeInformation.FrameworkDescription and assemblies likeSystem.Private.CoreLib, Version=8.0.0.0 in AppDomain).
  2. Target .NET 8 assembly is loaded intoSystem.AppDomain.CurrentDomain.GetAssemblies().
  3. clr.AddReference("Path/To/Assembly.dll") completes without error.
  4. Importing the assembly's namespace (e.g.,import MyNamespace) succeeds.
  5. Attempting to access a type (e.g.,MyNamespace.MyClass) results inAttributeError: module 'MyNamespace' has no attribute 'MyClass'.
  6. Alternatively, if a package's Python module triesfrom MyNamespace import MyClass (afterclr.AddReference in__init__.py), it fails withImportError: cannot import name 'MyClass' from 'MyNamespace'.
  7. Theclr module object consistently lacks theReferences attribute (i.e.,hasattr(clr, "References") isFalse) after .NET CoreCLR initialization.
  8. clr.FindAssembly("AssemblyName") returns a string path to the DLL, not anAssembly object.

Expected Behavior:

  • Types from .NET 8 assemblies should be accessible in Python afterclr.AddReference() and importing the namespace.
  • NoAttributeError orImportError should occur when accessing correctly referenced .NET types.
  • The behavior ofclr.References andclr.FindAssembly() with .NET CoreCLR should ideally be consistent with .NET Framework or clearly documented if different.

Steps to Reproduce (Minimal Case):

  1. Create a simple .NET 8 Class Library (MinimalNet8Lib):

    • MinimalNet8Lib.csproj:
      <ProjectSdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>net8.0</TargetFramework>    <ImplicitUsings>enable</ImplicitUsings>    <Nullable>enable</Nullable>    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>  </PropertyGroup></Project>
    • Class1.cs (or e.g.,Greeter.cs):
      namespaceMinimalNet8Lib;publicclassGreeter{publicstaticstringSayHello(stringname){return$"Hello,{name} from .NET 8!";}publicstringInstanceHello(stringname){return$"Instance hello to{name} from .NET 8!";}}
    • Build the library:dotnet build -c Release
  2. Create a Python Test Script (test_minimal_net8.py):

    importosimportsysfrompathlibimportPathprint(f"Python version:{sys.version}")print(f"Python executable:{sys.executable}")# --- Crucial: Set PYTHONNET_RUNTIME to coreclr BEFORE pythonnet import ---os.environ["PYTHONNET_RUNTIME"]="coreclr"try:print("Attempting to import pythonnet and clr_loader...")importpythonnetimportclr_loaderprint(f"pythonnet version:{pythonnet.__version__}")print(f"clr_loader version:{clr_loader.__version__}")exceptExceptionase:print(f"Error importing pythonnet/clr_loader:{e}")sys.exit(1)# --- Setup Paths ---# Adjust this path to your MinimalNet8Lib.dll# Assumes the script is run from a directory where MinimalNet8Lib/bin/Release/net8.0/MinimalNet8Lib.dll existsscript_dir=Path(__file__).parent.resolve()dll_path=script_dir/"MinimalNet8Lib"/"bin"/"Release"/"net8.0"/"MinimalNet8Lib.dll"runtime_config_path=script_dir/"MinimalNet8Lib"/"bin"/"Release"/"net8.0"/"MinimalNet8Lib.runtimeconfig.json"# Optional: Specify DOTNET_ROOT if not discoverable# dotnet_root = Path(os.environ.get("DOTNET_ROOT", "C:/Program Files/dotnet"))print(f"Target DLL:{dll_path}")print(f"Runtime Config:{runtime_config_path}")ifnotdll_path.exists():print(f"ERROR: DLL not found at{dll_path}")sys.exit(1)ifnotruntime_config_path.exists():print(f"ERROR: Runtime config not found at{runtime_config_path}")sys.exit(1)try:print("\n--- Initializing .NET CoreCLR Runtime ---")# Using clr_loader to get the runtimert=clr_loader.get_coreclr(runtime_config=str(runtime_config_path))#, dotnet_root=str(dotnet_root)print(f"CoreCLR runtime object:{rt}")print("Setting pythonnet runtime...")pythonnet.set_runtime(rt)print("Pythonnet runtime set.")print("Attempting to import clr...")importclrprint("Successfully imported clr.")print(f"clr module:{clr}")ifhasattr(clr,"__version__"):print(f"clr (pythonnet) version attribute:{clr.__version__}")exceptExceptionase:print(f"ERROR during runtime initialization or clr import:{e}")importtracebacktraceback.print_exc()sys.exit(1)print("\n--- Runtime and Assembly Diagnostics ---")try:fromSystemimportEnvironment,AppDomainfromSystem.Runtime.InteropServicesimportRuntimeInformationprint(f"PythonEngine.Version:{pythonnet.get_version()}")print(f"PythonEngine.IsInitialized:{pythonnet.is_initialized()}")print(f"System.Environment.Version:{Environment.Version}")print(f"RuntimeInformation.FrameworkDescription:{RuntimeInformation.FrameworkDescription}")print(f"Adding reference to:{str(dll_path)}")clr.AddReference(str(dll_path))print("clr.AddReference completed.")print("Assemblies in Current AppDomain:")forassemblyinAppDomain.CurrentDomain.GetAssemblies():print(f"  -{assembly.FullName}")if"MinimalNet8Lib"inassembly.FullName:print(f"    FOUND MinimalNet8Lib:{assembly.FullName}, Location:{assembly.Location}")print(f"clr.FindAssembly('MinimalNet8Lib'):{clr.FindAssembly('MinimalNet8Lib')}")print(f"hasattr(clr, 'References'):{hasattr(clr,'References')}")ifhasattr(clr,'References')andclr.ReferencesisnotNone:print(f"Number of clr.References:{len(clr.References)}")else:print("clr.References attribute is missing or None.")exceptExceptionase:print(f"Error during diagnostics:{e}")importtracebacktraceback.print_exc()# Continue to type access attemptprint("\n--- Attempting to Access .NET Types ---")try:print("Attempting: import MinimalNet8Lib")importMinimalNet8Libprint("Successfully imported MinimalNet8Lib namespace.")print("Attempting: greeter = MinimalNet8Lib.Greeter()")greeter=MinimalNet8Lib.Greeter()# This is where AttributeError typically occursprint(f"Successfully created Greeter instance:{greeter}")print(f"Calling instance method:{greeter.InstanceHello('Python')}")print(f"Calling static method:{MinimalNet8Lib.Greeter.SayHello('Python')}")print("\nSUCCESS: .NET 8 types accessed successfully!")exceptAttributeErrorasae:print(f"FAILURE: AttributeError:{ae}")print("This indicates types from the .NET 8 assembly were not exposed correctly.")importtracebacktraceback.print_exc()exceptExceptionase:print(f"FAILURE: An unexpected error occurred:{e}")importtracebacktraceback.print_exc()print("\nScript finished.")
  3. Run the Python script:
    python test_minimal_net8.py
    This will show theAttributeError.

  4. Test with .NET 9 (Works):

    • ChangeTargetFramework inMinimalNet8Lib.csproj tonet9.0.
    • Rebuild:dotnet build -c Release.
    • Updatedll_path andruntime_config_path intest_minimal_net8.py to point to thenet9.0 outputs.
    • Ensure .NET 9 SDK/Runtime is installed and discoverable.
    • Runtest_minimal_net8.py. The script should complete successfully, accessing the .NET types.

Additional Notes:

  • The issue has been observed withpythonnet versions 3.0.3 and 3.0.5.
  • The problem is reproducible with both a minimal class library and more complex, real-world libraries (e.g.,Tableau.Migration.dll v5.0.1, which targets onlynet8.0 and usespythonnet.load("coreclr") in its__init__.py, leading to anImportError when its Python submodules try to import the .NET types).
  • SettingPYTHONNET_RUNTIME=coreclr and usingclr_loader.get_coreclr() followed bypythonnet.set_runtime() beforeimport clr is a reliable way to initialize .NET CoreCLR. Simpler methods like justpythonnet.load("coreclr") orimport clr can sometimes lead to .NET Framework being loaded if not carefully managed, but the type exposure issue persists even with explicit and correct .NET 8 CoreCLR initialization.

We believe this is a significant issue for users attempting to leverage .NET 8 libraries with Python viapythonnet. The fact that it works seamlessly with .NET 9 suggests a specific interaction problem with .NET 8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp