You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Could not load file or assembly 'Python.Runtime, Version=2.4.0.0... #665
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
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.
@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;
}
}
}
@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.
@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.
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.
Activity
den-run-ai commentedon Apr 27, 2018
@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 commentedon Apr 27, 2018
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 commentedon Apr 27, 2018
@tomunger the solution is simple - don't use GAC!
tomunger commentedon Apr 27, 2018
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 toPythonEngine.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 commentedon Apr 27, 2018
@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 commentedon Apr 28, 2018
Did you also check about this(NTFS Security, Blocking)?
#655
tomunger commentedon Apr 29, 2018
@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
AssemblyResolveevent and I had not explored that. Turns out that solves my problem. Here's the code that loads Python.Runtime from the python directory.den-run-ai commentedon Apr 30, 2018
@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 commentedon 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 commentedon Jan 12, 2019
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 commentedon Jan 12, 2019
@dmitriyse can you share the branch?
dmitriyse commentedon Jan 12, 2019
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.