I am trying to use a .NET Core library inside a Jupyter Notebook python script by using PythonNet. Support for .NET Core was added recently (see https://github.com/pythonnet/pythonnet/issues/984#issuecomment-778786164) but I am still getting a No module named 'TestAppCore' error.
I don't have an issue using a .NET Framework library with PythonNet, only .NET Core. Any help with diagnosing and fixing the issue would be greatly appreciated.
The C# library I'm trying to get working is a simple class library project with no dependencies at all. Below is the entirety of the code:
namespace TestAppCore
{
public class Foo
{
public int ID { get; set; }
public Foo(int id)
{
ID = id;
}
public int Add(int a, int b)
{
return a + b;
}
}
}
Here is the python script:
from clr_loader import get_coreclr
from pythonnet import set_runtime
rt = get_coreclr("D:\src\Test.runtimeconfig.json")
set_runtime(rt)
import clr
import sys
sys.path.append(r"D:\src\TestAppCore")
clr.AddReference(r"TestAppCore")
from TestAppCore import Foo
foo = Foo(5)
print(foo.ID)
res = foo.Add(1, 2)
print(res)
Here is the output:
Finally, here is the runtime config I am using:
{
"runtimeOptions": {
"tfm": "netcoreapp3.1",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.1.0"
}
}
}
.NET Core: 3.1
python version: 3.7
pythonnet: 3.0.0.dev1
clr-loader: 0.1.6
I suspect that you are getting the DLL path wrong.
This worked for me:
from clr_loader import get_coreclr
from pythonnet import set_runtime
set_runtime(get_coreclr("pythonnetconfig.json"))
import clr
clr.AddReference("C:/Path/To/Interface.dll")
from Interface import Foo
foo = Foo()
Using
Python 3.8.10
pythonnet 3.0.0a1
clr-loader 0.1.7
C# DLL (Class Library) targeting .NET Core 3.1
pythonnetconfig.json exactly as you posted.
I never got it to work with .NET Core 3.1. For me it worked with .NET Framework 4.8 and pythonnet 2.5.2. See my other answer for more details.
I have a similar problem and found out that if the DLL and the namespace are the same, then it fails. In my case, following pythonnet tutorial:
Calculate.sln contains Calc.cs, with
namespace Calculate; // recommended by VS
class Calc { ... }
Then in Python
clr.AddReference("Calculate") # Assuming sys.path correct setting
from Calculate import Calc
Then:
ImportError: cannot import name 'Calc' from 'Calculate' (unknown location)
But with:
namespace CalculateNS; // different name than Calculate.dll
class Calc { ... }
Then in Python
clr.AddReference("Calculate") # Assuming sys.path correct setting
from CalculateNS import Calc
it works... side effects, pylance known Calculate module but not CalculateNS :-(
Anyone experimented this? I saw lot of answers that have never been tested I guess, only thoughts
Using .NET 6.0 Framework.
Related
I have a C# piece that generates a DLL which I'm trying to invoke from Python. The C# prototype is as follow:
public Main(NationalInstruments.TestStand.Interop.API.SequenceContext sequenceContext){
public void ShowFullOptions(out bool errorOccurred, out int errorCode, out String errorMsg) {
[...]
}
}
I followed this post which explains how to achieve to pass "out" parameters from python, without success since clr.Reference does not exist and throw me the error:
AttributeError: module 'clr' has no attribute 'Reference'
I have pythonnet installed, version 2.3.
My python code:
import clr
dll_path = R"thatDllPath.dll"
clr.AddReference(dll_path)
from Flamenco_Calibration_Interface import Main
import System
my_instance = Main(None)
v1 = clr.Reference[System.Boolean](False)
v2 = clr.Reference[System.Int64](1)
v3 = clr.Reference[System.String]("")
a = my_instance.ShowFullOptions(v1,v2,v3)
I have checked that the DLL path is good and I am able to successfully call the C# method if I overload "ShowFullOptions" with a version without any arguments.
The main problem resides in that I have the "out" keyword in the C# method prototype.
How do you properly generate argument in python so they are accepted as "out" within C# ?
Any help much appreciated.
I have a script that runs without any problems using Pycharm / Spyder but when I try to run in using Iron Python on c# I get the following error: 'No module named keras.callbacks'
Here is the code I am using to run the script:
public string PatchParameter(string parameter, int serviceid)
{
var engine = Python.CreateEngine(); // Extract Python language engine from their grasp
var scope = engine.CreateScope(); // Introduce Python namespace (scope)
var d = new Dictionary<string, object>
{
{ "serviceid", serviceid},
{ "parameter", parameter}
}; // Add some sample parameters. Notice that there is no need in specifically setting the object type, interpreter will do that part for us in the script properly with high probability
scope.SetVariable("params", d); // This will be the name of the dictionary in python script, initialized with previously created .NET Dictionary
ICollection<string> searchPaths = engine.GetSearchPaths();
searchPaths.Add(#"D:\Projects\xxx");
searchPaths.Add(#"C:\Users\xxx\Anaconda3");
searchPaths.Add(#"C:\Users\xxx\Anaconda3\Library\bin");
searchPaths.Add(#"C:\Users\xxx\Anaconda3\Scripts");
searchPaths.Add(#"D:\Projects\SmartTrader\venv");
searchPaths.Add(#"D:\Projects\SmartTrader\venv\Scripts");
searchPaths.Add("..\\..");
engine.SetSearchPaths(searchPaths);
ScriptSource source = engine.CreateScriptSourceFromFile(#"D:\Projects\xxx\Main.py"); // Load the script
object result = source.Execute(scope);
parameter = scope.GetVariable<string>("parameter"); // To get the finally set variable 'parameter' from the python script
return parameter;
}
In the comments it was suggested to add the virtual environment to the search paths, that still did not work though.
I also tried running it through regular CMD and it did not work as well:
C:\Users\xxx\Anaconda3>python.exe D:\Projects\xxx\Main.py
Traceback (most recent call last):
File "D:\Projects\xxx\Main.py", line 7, in <module>
import Config as cfg
File "D:\Projects\xxx\Config.py", line 2, in <module>
from keras.callbacks import EarlyStopping, ModelCheckpoint
ModuleNotFoundError: No module named 'keras'
I tried adding the Anaconda paths to its search paths but it did not work.
What am I missing?
Thanks
Amit
You can't run an Anaconda environment with IronPython, sorry.
(You especially probably can't run Keras / Tensorflow on IronPython.)
I've created a python binding for one of my projects a while back and just now wanted to pick it up again.
The binding was no longer working as python was no longer able to import it - this all was working fine back then.
I've then decided to break it down to the simplest possible example:
binding.cpp
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(TestBinding, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
}
CMakeLists.txt:
cmake_minimum_required( VERSION 3.2 )
project(TestBinding)
add_subdirectory(pybind11) # or find_package(pybind11)
pybind11_add_module(TestBinding binding.cpp)
# Configure project to inject source path as include directory on dependent projects
target_include_directories( TestBinding
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/pybind11/include/> )
set_target_properties( TestBinding
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
PREFIX ""
SUFFIX ".so"
)
Then I have a very simple test.py file which goes like this:
sys.path.insert(0, "/path/to/so/lib/")
from TestBinding import *
...which once executed always gives me the following error:
from TestBinding import *
ModuleNotFoundError: No module named 'TestBinding'
I have literally no idea anymore what in the world could have changed from when it worked just fine and now.
Here are some more informations about my working environment:
Windows 10
Visual Studio 15 2017 Win64
Python 3.7 (also tried 3.5 and 3.6)
Am I missing anything really obvious?
I've been able to resolve this by removing the SUFFIX ".so" rule from my CMakeLists.txt.
This was needed back when I've initially created my bindings, but it no longer is apparently.
I have the same problem as you. After checking, it is found that the problem is caused by the inconsistency between the python version of pybind11 and the python version of the local environment. My problem was solved when I adjusted to the same python version.
I'm trying to use some Python Code in my Swift project with PythonKit. In order to do that, I've downloaded the new Xcode 11 to add PythonKit as Swift Package.
After adding PythonKit with Swift Package, I have these project dependencies right here.
I want to use my Python code at the start of my app, so I put the call for Python code in my App Delegate, in the application function.
import UIKit
import PythonKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let sys = Python.import("sys")
print("Python Version: \(sys.version)")
sys.path.append("/Users/me/Documents/MyProject/MyPackage/my_python_main_file")
let pythonAPI = Python.import("my_python_main_file")
pythonAPI.main_function.call()
return true
}
After running my project, I get the following error :
Fatal error: Python library not found. Set the PYTHON_LIBRARY environment variable with the path to a Python library.
I tried to follow the different steps with Breakpoints to know where the code actually crashes. So here is the different stages the PythonKit goes through :
It goes inside PythonLibrary init() and produces the error :
guard let pythonLibraryHandle = PythonLibrary.loadPythonLibrary() else {
fatalError("""
Python library not found. Set the \(Environment.library.key) \
environment variable with the path to a Python library.
""")
}
After investigation, it is because of the call of dlopen inside of loadPythonLibrary function
static func loadPythonLibrary(at path: String) -> UnsafeMutableRawPointer? {
log("Trying to load library at '\(path)'...")
#if canImport(Darwin) || canImport(Glibc)
// Must be RTLD_GLOBAL because subsequent .so files from the imported python
// modules may depend on this .so file.
let pythonLibraryHandle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)
#elseif os(Windows)
let pythonLibraryHandle = UnsafeMutableRawPointer(LoadLibraryA(path))
#endif
if pythonLibraryHandle != nil {
log("Library at '\(path)' was sucessfully loaded.")
}
return pythonLibraryHandle
}
This functions returns nil, which is due to dlopen function returning nil.
However, I checked the path given as parameter to loadPythonLibrary(at : path) and it appeared to be correct (in Terminal I tried to do cd to the following path and it worked) :
/usr/local/Frameworks/Python.framework/Versions/2.7/Python
I am using Python 2.7 in my code.
Do you know why dlopen would return nil in my case ?
You can do it now using my fork of PythonKit at https://github.com/kewlbear/PythonKit. This package depends on my other package https://github.com/kewlbear/Python-iOS. Ultimately Python will be embedded in the app. Currently Python 3.8 is used.
I'm looking to try and run Jasper reports (that have been written in iReports and exported to xml) from within a python application, without having to communicate with a JasperServer instance. Is this possible?
I've done some googling and only come across a 2 year old SO question (where the suggested answer actually requires JasperServer):
Run jasper report (created with iReport) from within python without jasperserver?
And something that looks kind of promising, except for the "It is obsolete" in the title:
http://code.activestate.com/recipes/576969-python-jasperreport-integration-it-is-obsolete/
I'm hoping it's obsolete because this is now an officially supported thing (dream on, Dave), but I can't find anything about it, if it is.
Actually Jasper Reports are not implemented in Python, so the only way to have it serving to your Python code is to have Jasper Server running and awaiting Python requests over REST or other remote way of communication.
Simply - no way to have Jasper without Jasper (server) in Python
I used py4j. I had to write a small program in java.
Using this as an example, it was simple.
It was more difficult to configure the build environment and put all the dependencies for printing qr-codes.
Python example:
from py4j.java_gateway import JavaGateway
gateway = JavaGateway()
gateway.entry_point.pdf_from_json('e:/test.jasper', 'e:/test.json', 'e:/test.pdf')
Java example:
package jasper4py;
import py4j.GatewayServer;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JsonDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
public class JasperEntryPoint {
public static void main(String[] args) {
GatewayServer gatewayServer = new GatewayServer(new JasperEntryPoint());
gatewayServer.start();
System.out.println("Gateway Server Started");
}
public void pdf_from_json(String report, String data, String result) throws JRException, IOException {
Map<String, Object> parameters = new HashMap<String, Object>();
JsonDataSource dataSource = new JsonDataSource(JRLoader.getLocationInputStream(data));
JasperPrint jasperPrint = JasperFillManager.fillReport(report, parameters, dataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, result);
}
}