Skip to content

Could not load file or assembly 'Python.Runtime, Version=2.4.0.0... #665

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

Closed
tomunger opened this issue Apr 27, 2018 · 12 comments
Closed

Could not load file or assembly 'Python.Runtime, Version=2.4.0.0... #665

tomunger opened this issue Apr 27, 2018 · 12 comments

Comments

@tomunger
Copy link

Environment

  • Pythonnet version: 2.4.00
  • Python version: 2.7.13
  • Operating System: Windows 7

Details

  • Describe what you were trying to get done.

I have used pip install git+https://github.com/pythonnet/pythonnet
to install latest python net.

I've created a .NET visual studio 2015 project to make calls to Python. I reference the Python.Runtime.dll file in the project. When I let it get copied to the binary directory of my project calls to CPython work fine.

Now, I don't want to bundle the DLL with my application. As I understand, different versions work with different versions of CPython. I would like to load Python.Runtime.dll from Lib\site-packages so I get version appropriate for version of Python installed on the system. I change properties of the PythonRuntime.dll reference to NOT copy the DLL to bin directory. Now I get the error:

An unhandled exception of type 'System.IO.FileNotFoundException' occurred in PyRunner.exe
Additional information: Could not load file or assembly 'Python.Runtime, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

This minimal program causes the error.

using Python.Runtime;

namespace PyRunner
{
	class ErrorExample
	{
		static void Main(string[] args)
		{
			PythonEngine.Initialize();
		}
	}
}

I've tracked down other issues related to this but none seem to simply be that the DLL is not found.

When I try to install the assembly in the GAC I get

>gacutil /i Lib\site-packages\Python.Runtime.dll
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Failure adding assembly to the cache: Attempt to install an assembly without a strong name

Thanks

@den-run-ai
Copy link
Contributor

@tomunger use this tool to strongly sign Python.Runtime.DLL with a key, e.g. the one provided with pythonnet:

https://github.com/brutaldev/StrongNameSigner

@tomunger
Copy link
Author

Does this mean that I must sign the DLL on all systems my application is used on? That does not seem scalable. Also, I came across articles against strong naming and microsoft suggests against it.

How do other apps that embed Python solve this? It seems that it should be very simple...

@den-run-ai
Copy link
Contributor

@tomunger the solution is simple - don't use GAC!

@tomunger
Copy link
Author

I'm trying to not use GAC! Assembly.LoadFrom("filepath") will happily load Python.runtime assembly. But this does not resolve the static references. Soon as my code gets close to PythonEngine.Initilize() it fails with assembly-not-found error. My current solution is to copy the .dll file into application directory. I feels like I'm missing something simple and obvious here but all examples found by Google show me how to do thinks I know and which do not solve the problem.
Thanks for your suggestions.

@den-run-ai
Copy link
Contributor

@tomunger this has nothing to do with pythonnet, but you can set custom load path for reference DLLs:

https://stackoverflow.com/q/1892492/2230844

@icetiger1974
Copy link
Contributor

Did you also check about this(NTFS Security, Blocking)?
#655

@tomunger
Copy link
Author

@denfromufa thanks for that link. I know about private path and it does not resolve my issue. The standard approach is to distribute DLLs for the assemblies your application depends on WITH your application. However, in the case of Python.Net I don't want to do this. Different versions of Python require different DLLs (right?). What I want to do is use the DLL installed with Python - thus not in my application directory anywhere.
The bottom of that thread had an example of using the AssemblyResolve event and I had not explored that. Turns out that solves my problem. Here's the code that loads Python.Runtime from the python directory.

public class PythonResolver
{
	public const string LIBS_PATH = "Lib\\site-packages";
	public const string ASSEMBLY_FILE = "Python.Runtime.dll";
	private string _pythonHome;

	public PythonResolver(string pythonHome)
	{
		_pythonHome = pythonHome;
		AppDomain.CurrentDomain.AssemblyResolve += this.ResolvePython;
	}

	private Assembly ResolvePython(object sender, ResolveEventArgs args)
	{
		// Forbid non handled dll's
		if (!args.Name.Contains("Python.Runtime"))
		{
			return null;
		}
		string targetPath = Path.Combine(_pythonHome, LIBS_PATH, ASSEMBLY_FILE);

		try
		{
			return Assembly.LoadFile(targetPath);
		}
		catch (Exception)
		{
			return null;
		}
	}
}

@den-run-ai
Copy link
Contributor

@tomunger good finding! Yes, pythonnet has some build time compiler flags for specific Python versions even in Python.Runtime.DLL CLR assembly. @dmitriyse was working on approach to resolve these APIs at runtime, but I'm not sure how far he was able to accomplish this.

@lostmsu
Copy link
Member

lostmsu commented Jan 12, 2019

@dmitriyse @denfromufa is there an issue tracking this? I am also interested in a generic binding, that could be used with any Python installation across platforms.

@dmitriyse
Copy link
Contributor

I have made great work to isolate C-Calls (that gave an ability to load different python dlls at runtime). But it was so big changes that nobody elso wants to work with that.
Now this work should be performed again due to lots of changes in the C-Calls code.

@lostmsu
Copy link
Member

lostmsu commented Jan 12, 2019

@dmitriyse can you share the branch?

@dmitriyse
Copy link
Contributor

Sorry, this branch is not in GH now.
And probably I have already delete it from my working computer.

I have spent around 4 working days to carefully add indirection into runtime.cs C-Calls and all other wrapping code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants