Why does Jython not find this module? [duplicate] - java

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to run a python script from java?
I am running a Python script using Jython and got this error:
Exception in thread "main" Traceback (innermost last): File "C:\Facebook\LoginPython\Facebook.py", line 5, in ? ImportError: no module named cookielib
Why doesn't this work?

A little bit more about using Jython - had my share of problems with that as well. Note that this may not be the best way to do it, but it works fine for me.
I assume you want to call a function foo in module bar from your Java code that takes a string argument and returns a string:
PythonInterpreter interpreter = new PythonInterpreter();
// Append directory containing module to python search path and import it
interpreter.exec("import sys\n" + "sys.path.append(pathToModule)\n" +
"from bar import foo");
PyObject meth = interpreter.get("foo");
PyObject result = meth.__call__(new PyString("Test!"));
String real_result = (String) result.__tojava__(String.class);
The sys.path.append() part is only necessary if your module isn't part of the Python search path by default, which may very well be the problem if you get Import or Module not find errors.
Also you need to cast the objects between the java and python versions, you'll need to look that up if necessary, so far I only needed primitive types that were easy to cast, not sure if it's as easy for arbitrary java objects.

Use Jython to run Python on the JVM. Use PyDev to develop with Python (or Jython) on Eclipse.

Related

Run matlab function in java class in absence of matlab environment

I want to use matlab function in java application. I create java package from my function by deploytool in matlab. Now, how can i use this package? Can only import the jar file created by deploytool in my java project and use its function?
After a lot of googling, I used this toturial but in the final step, i get error "could not load file".
Also i read about MatlabControl, but in this solution, we should have matlab environment in our system to java code running. But i will run my final app in systems that may not have matlab at all.
So i need a solution to run matlab function in java class even in absence of matlab environment.
Finally I solve my problem. the solution step by step is as follows:
write matlab function:
function y = makesqr(x)
y = magic(x);
Use deploytool in matlab and create java package.
3.create new java application in Eclipse and add main class. import javabuilde.jar and makesqr.jar:
import com.mathworks.toolbox.javabuilder.MWArray;
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import makesqr.Class1;
and main.java:
public class main {
public static void main(String[] args) {
MWNumericArray n = null;
Object[] result = null;
Class1 theMagic = null;
try
{
n = new MWNumericArray(Double.valueOf(5),MWClassID.DOUBLE);
theMagic = new Class1();
result = theMagic.makesqr(1, n);
System.out.println(result[0]);
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
finally
{
MWArray.disposeArray(n);
MWArray.disposeArray(result);
theMagic.dispose();
}
}
}
add javabuilder.jar and makesqr.jar to java build path of your project.
run it.
the Double.valueOf(3), define the input for our function and the output is as follows:
8 1 6
3 5 7
4 9 2
I didn't get properly your problem. Did you already compile the jar file from Matlab code and you are trying to use that, or you are at the last step of the tutorial?
If your answer is the latest case, most probably you forgot the "." before the class path.
From tutorial you linked:
You must be sure to place a dot (.) in the first position of the class path. If it not, you get a message stating that Java cannot load the class.
Also check if the matlab compiler path ("c:\Program Files\MATLAB\MATLAB Compiler Runtime\v82\toolbox\javabuilder\jar\javabuilder.jar" - in the tutorial) is correct for your system.

Python 2.7 subprocess call method not working to run java command

I am trying to use a python script to manipulate the input files for my java program. The way I am doing it is I am generating the file name and passing it to subprocess.call() method to execute. Here is my program:
def execJava(self):
self.thisCmd="pause"
call(self.javaCmd,shell=True)
call(self.pauseCmd,shell=True)
Where,
self.javaCmd = 'java -ea -esa -Xfuture -Xss64m -classpath "C:\FVSDK_9_1_1\lib\x86_64\msc_12.0-sse2_crtdll\*" -Djava.library.path="C:\FVSDK_9_1_1\lib\x86_64\msc_12.0-sse2_crtdll;C:\FVSDK_9_1_1\lib\x86_64\share" com.cognitec.jfrsdk.examples.MatchFIRAgainstGallery C:\FVSDK_9_1_1\etc\frsdk.cfg 0 .\tmp\frsdk-scratch\probe_1.fir .\tmp\test\*'
Yes, it's a long complex java instruction but when I run it in the command prompt it works fine. Only when I pass it as a string it doesn't run and returns:
Exception in thread "main" java.lang.Error
After some exploration into the problem, I have discovered that it is due to \x, \t in the instruction, so it is executing
.\tmp\test\*
as
mp est\*
as it replaces \t with tab space while executing. I have looked up quite a bit and didn't find any solution. Any help is much appreciated.
Use forward slashes "/" instead of back slashes "\" for your paths.

Jpype passing arguments to Java

I have a java programmer with following line
service.loadPropertiesForItems(Inbox, new PropertySet(ItemSchema.Subject, ItemSchema.Body));
Program calls classes and methods from external jars.
I want to write equivalent code in python which calls external jars like my java program does.
Using Jpype I implemented the code but it fails on following line
service.loadPropertiesForItems(inbox, ewsPkg.PropertySet(ewsPkg.ItemSchema.Subject, ewsPkg.ItemSchema.Body))
Here PropertySet, ItemSchema are classes which I use from external jar.
ItemSchema.Subject and ewsPkg.ItemSchema.Body are class type
Running the code I get following error on line mentioned above -
service.loadPropertiesForItems(inbox, ewsPkg.PropertySet(ewsPkg.ItemSchema.Subject, ewsPkg.ItemSchema.Body))
File "C:\Python27\lib\site-packages\jpype\_jclass.py", line 79, in _javaInit
self.__javaobject__ = self.__class__.__javaclass__.newClassInstance(*args)
RuntimeError: No matching overloads found. at src/native/common/jp_method.cpp:121
Thanks
As suggested by Martin https://github.com/originell/jpype/issues/117
following code works well
ItemSchema = ewsPkg.ItemSchema
PropertyDefinition = ewsPkg.PropertyDefinition
Subject = ItemSchema.Subject
Body = ItemSchema.Body
args = JArray(PropertyDefinition)([ItemSchema.Subject, Body])
PropertySet = ewsPkg.PropertySet(args)

How to save a Java object in Jython/Python

I'm building a Python UI using Tkinter. For the needs of the program, I've to connect Python with Java to do some stuff, so I'm using a simple Jython script as a linker. I cant use Tkinter with Jython because it's not supported.
Python (ui.py) -> Jython (linker.py) -> Java (compiled in jars)
To call the Jython function in Python I use subprocess as follows:
ui.py:
cmd = 'jython linker.py"'
my_env = os.environ
my_env["JYTHONPATH"] = tons_of_jars
subprocess.Popen(cmd, shell=True, env=my_env)
Then, in the Jython file, linker.py, I import the Java classes already added on the JYTHONPATH, and I create an object with the name m and call to some functions of the Java class.
linker.py:
import handler.handler
m = handler.handler(foo, moo, bar)
m.schedule(moo)
m.getFullCalendar()
m.printgantt()
The thing is that I've created a m object, that will be destroyed after the execution of jython linker.py ends.
So the question is: Is possible to save that m object somewhere so I can call it from ui.py whenever I want? If it's not possible, is there any other way to do this?
Thanks in advance.
I finally solved it by using ObjectOutputStream.
from java import io
def saveObject(x, fname="object.bin"):
outs = io.ObjectOutputStream(io.FileOutputStream(fname))
outs.writeObject(x)
outs.close()
def loadObject(fname="object.bin"):
ins = io.ObjectInputStream(io.FileInputStream(fname))
x=ins.readObject()
ins.close()
return x

Calling clojure from java

Most of the top google hits for "calling clojure from java" are outdated and recommend using clojure.lang.RT to compile the source code. Could you help with a clear explanation of how to call Clojure from Java assuming you have already built a jar from the Clojure project and included it in the classpath?
Update: Since this answer was posted, some of the tools available have changed. After the original answer, there is an update including information on how to build the example with current tools.
It isn't quite as simple as compiling to a jar and calling the internal methods. There do seem to be a few tricks to make it all work though. Here's an example of a simple Clojure file that can be compiled to a jar:
(ns com.domain.tiny
(:gen-class
:name com.domain.tiny
:methods [#^{:static true} [binomial [int int] double]]))
(defn binomial
"Calculate the binomial coefficient."
[n k]
(let [a (inc n)]
(loop [b 1
c 1]
(if (> b k)
c
(recur (inc b) (* (/ (- a b) b) c))))))
(defn -binomial
"A Java-callable wrapper around the 'binomial' function."
[n k]
(binomial n k))
(defn -main []
(println (str "(binomial 5 3): " (binomial 5 3)))
(println (str "(binomial 10042 111): " (binomial 10042 111)))
)
If you run it, you should see something like:
(binomial 5 3): 10
(binomial 10042 111): 49068389575068144946633777...
And here's a Java program that calls the -binomial function in the tiny.jar.
import com.domain.tiny;
public class Main {
public static void main(String[] args) {
System.out.println("(binomial 5 3): " + tiny.binomial(5, 3));
System.out.println("(binomial 10042, 111): " + tiny.binomial(10042, 111));
}
}
It's output is:
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
The first piece of magic is using the :methods keyword in the gen-class statement. That seems to be required to let you access the Clojure function something like static methods in Java.
The second thing is to create a wrapper function that can be called by Java. Notice that the second version of -binomial has a dash in front of it.
And of course the Clojure jar itself must be on the class path. This example used the Clojure-1.1.0 jar.
Update: This answer has been re-tested using the following tools:
Clojure 1.5.1
Leiningen 2.1.3
JDK 1.7.0 Update 25
The Clojure Part
First create a project and associated directory structure using Leiningen:
C:\projects>lein new com.domain.tiny
Now, change to the project directory.
C:\projects>cd com.domain.tiny
In the project directory, open the project.clj file and edit it such that the contents are as shown below.
(defproject com.domain.tiny "0.1.0-SNAPSHOT"
:description "An example of stand alone Clojure-Java interop"
:url "http://clarkonium.net/2013/06/java-clojure-interop-an-update/"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:aot :all
:main com.domain.tiny)
Now, make sure all of the dependencies (Clojure) are available.
C:\projects\com.domain.tiny>lein deps
You may see a message about downloading the Clojure jar at this point.
Now edit the Clojure file C:\projects\com.domain.tiny\src\com\domain\tiny.clj such that it contains the Clojure program shown in the original answer. (This file was created when Leiningen created the project.)
Much of the magic here is in the namespace declaration. The :gen-class tells the system to create a class named com.domain.tiny with a single static method called binomial, a function taking two integer arguments and returning a double. There are two similarly named functions binomial, a traditional Clojure function, and -binomial and wrapper accessible from Java. Note the hyphen in the function name -binomial. The default prefix is a hyphen, but it can be changed to something else if desired. The -main function just makes a couple of calls to the binomial function to assure that we are getting the correct results. To do that, compile the class and run the program.
C:\projects\com.domain.tiny>lein run
You should see output shown in the original answer.
Now package it up in a jar and put it someplace convenient. Copy the Clojure jar there too.
C:\projects\com.domain.tiny>lein jar
Created C:\projects\com.domain.tiny\target\com.domain.tiny-0.1.0-SNAPSHOT.jar
C:\projects\com.domain.tiny>mkdir \target\lib
C:\projects\com.domain.tiny>copy target\com.domain.tiny-0.1.0-SNAPSHOT.jar target\lib\
1 file(s) copied.
C:\projects\com.domain.tiny>copy "C:<path to clojure jar>\clojure-1.5.1.jar" target\lib\
1 file(s) copied.
The Java Part
Leiningen has a built-in task, lein-javac, that should be able to help with the Java compilation. Unfortunately, it seems to be broken in version 2.1.3. It can't find the installed JDK and it can't find the Maven repository. The paths to both have embedded spaces on my system. I assume that is the problem. Any Java IDE could handle the compilation and packaging too. But for this post, we're going old school and doing it at the command line.
First create the file Main.java with the contents shown in the original answer.
To compile java part
javac -g -cp target\com.domain.tiny-0.1.0-SNAPSHOT.jar -d target\src\com\domain\Main.java
Now create a file with some meta-information to add to the jar we want to build. In Manifest.txt, add the following text
Class-Path: lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
Main-Class: Main
Now package it all up into one big jar file, including our Clojure program and the Clojure jar.
C:\projects\com.domain.tiny\target>jar cfm Interop.jar Manifest.txt Main.class lib\com.domain.tiny-0.1.0-SNAPSHOT.jar lib\clojure-1.5.1.jar
To run the program:
C:\projects\com.domain.tiny\target>java -jar Interop.jar
(binomial 5 3): 10.0
(binomial 10042, 111): 4.9068389575068143E263
The output is essentially identical to that produced by Clojure alone, but the result has been converted to a Java double.
As mentioned, a Java IDE will probably take care of the messy compilation arguments and the packaging.
As of Clojure 1.6.0, there is a new preferred way to load and invoke Clojure functions. This method is now preferred to calling RT directly (and supersedes many of the other answers here). The javadoc is here - the main entry point is clojure.java.api.Clojure.
To lookup and call a Clojure function:
IFn plus = Clojure.var("clojure.core", "+");
plus.invoke(1, 2);
Functions in clojure.core are automatically loaded. Other namespaces can be loaded via require:
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("clojure.set"));
IFns can be passed to higher order functions, e.g. the example below passes plus to read:
IFn map = Clojure.var("clojure.core", "map");
IFn inc = Clojure.var("clojure.core", "inc");
map.invoke(inc, Clojure.read("[1 2 3]"));
Most IFns in Clojure refer to functions. A few, however, refer to non-function data values. To access these, use deref instead of fn:
IFn printLength = Clojure.var("clojure.core", "*print-length*");
IFn deref = Clojure.var("clojure.core", "deref");
deref.invoke(printLength);
Sometimes (if using some other part of the Clojure runtime), you may need to ensure that the Clojure runtime is properly initialized - calling a method on the Clojure class is sufficient for this purpose. If you do not need to call a method on Clojure, then simply causing the class to load is sufficient (in the past there has been a similar recommendation to load the RT class; this is now preferred):
Class.forName("clojure.java.api.Clojure")
EDIT This answer was written in 2010, and worked at that time. See Alex Miller's answer for more modern solution.
What kind of code are calling from Java? If you have class generated with gen-class, then simply call it. If you want to call function from script, then look to following example.
If you want to evaluate code from string, inside Java, then you can use following code:
import clojure.lang.RT;
import clojure.lang.Var;
import clojure.lang.Compiler;
import java.io.StringReader;
public class Foo {
public static void main(String[] args) throws Exception {
// Load the Clojure script -- as a side effect this initializes the runtime.
String str = "(ns user) (defn foo [a b] (str a \" \" b))";
//RT.loadResourceScript("foo.clj");
Compiler.load(new StringReader(str));
// Get a reference to the foo function.
Var foo = RT.var("user", "foo");
// Call it!
Object result = foo.invoke("Hi", "there");
System.out.println(result);
}
}
EDIT: I wrote this answer almost three years ago. In Clojure 1.6 there is a proper API exactly for the purpose of calling Clojure from Java. Please Alex Miller's answer for up to date information.
Original answer from 2011:
As I see it, the simplest way (if you don't generate a class with AOT compilation) is to use clojure.lang.RT to access functions in clojure. With it you can mimic what you would have done in Clojure (no need to compile things in special ways):
;; Example usage of the "bar-fn" function from the "foo.ns" namespace from Clojure
(require 'foo.ns)
(foo.ns/bar-fn 1 2 3)
And in Java:
// Example usage of the "bar-fn" function from the "foo.ns" namespace from Java
import clojure.lang.RT;
import clojure.lang.Symbol;
...
RT.var("clojure.core", "require").invoke(Symbol.intern("foo.ns"));
RT.var("foo.ns", "bar-fn").invoke(1, 2, 3);
It is a bit more verbose in Java, but I hope it's clear that the pieces of code are equivalent.
This should work as long as Clojure and the source files (or compiled files) of your Clojure code is on the classpath.
I agree with clartaq's answer, but I felt that beginners could also use:
step-by-step information on how to actually get this running
information that's current for Clojure 1.3 and recent versions of leiningen.
a Clojure jar that also includes a main function, so it can be run standalone or linked as a library.
So I covered all that in this blog post.
The Clojure code looks like this:
(ns ThingOne.core
(:gen-class
:methods [#^{:static true} [foo [int] void]]))
(defn -foo [i] (println "Hello from Clojure. My input was " i))
(defn -main [] (println "Hello from Clojure -main." ))
The leiningen 1.7.1 project setup looks like this:
(defproject ThingOne "1.0.0-SNAPSHOT"
:description "Hello, Clojure"
:dependencies [[org.clojure/clojure "1.3.0"]]
:aot [ThingOne.core]
:main ThingOne.core)
The Java code looks like this:
import ThingOne.*;
class HelloJava {
public static void main(String[] args) {
System.out.println("Hello from Java!");
core.foo (12345);
}
}
Or you can also get all the code from this project on github.
This works with Clojure 1.5.0:
public class CljTest {
public static Object evalClj(String a) {
return clojure.lang.Compiler.load(new java.io.StringReader(a));
}
public static void main(String[] args) {
new clojure.lang.RT(); // needed since 1.5.0
System.out.println(evalClj("(+ 1 2)"));
}
}
If the use case is to include a JAR built with Clojure in a Java application, I have found having a separate namespace for the interface between the two worlds to be beneficial:
(ns example-app.interop
(:require [example-app.core :as core])
;; This example covers two-way communication: the Clojure library
;; relies on the wrapping Java app for some functionality (through
;; an interface that the Clojure library provides and the Java app
;; implements) and the Java app calls the Clojure library to perform
;; work. The latter case is covered by a class provided by the Clojure lib.
;;
;; This namespace should be AOT compiled.
;; The interface that the java app can implement
(gen-interface
:name com.example.WeatherForecast
:methods [[getTemperature [] Double]])
;; The class that the java app instantiates
(gen-class
:name com.example.HighTemperatureMailer
:state state
:init init
;; Dependency injection - take an instance of the previously defined
;; interface as a constructor argument
:constructors {[com.example.WeatherForecast] []}
:methods [[sendMails [] void]])
(defn -init [weather-forecast]
[[] {:weather-forecast weather-forecast}])
;; The actual work is done in the core namespace
(defn -sendMails
[this]
(core/send-mails (.state this)))
The core namespace can use the injected instance to accomplish its tasks:
(ns example-app.core)
(defn send-mails
[{:keys [weather-forecast]}]
(let [temp (.getTemperature weather-forecast)] ...))
For testing purposes, the interface can be stubbed:
(example-app.core/send-mails
(reify com.example.WeatherForecast (getTemperature [this] ...)))
Other technique that works also with other languages on top of JVM is to declare an interface for functions you want to call and then use 'proxy' function to create instance that implemennts them.
You can also use AOT compilation to create class files representing your clojure code. Read the documentation about compilation, gen-class and friends in the Clojure API docs for the details about how to do this, but in essence you will create a class that calls clojure functions for each method invocation.
Another alternative is to use the new defprotocol and deftype functionality, which will also require AOT compilation but provide better performance. I don't know the details of how to do this yet, but a question on the mailing list would probably do the trick.

Categories