从Python3调用Java类及输出错误处理(含JPype问题排查)
Let's work through your issues step by step to get Python 3 calling your Java class properly, with output and error logging sorted out.
1. Fix the ModuleNotFoundError: No module named 'jpype'
First off, the PyPI package for JPype is jpype1 (not just jpype). Install it via pip:
pip install jpype1
Then correct your import statement in Python (it's lowercase jpype, not uppercase):
import jpype as jp
2. Prepare Your Java Class for JPype Access
Your Java code has a few issues that block Python from interacting with it properly:
- The
testAll()method isprivate— Python can't access private Java methods, so change it topublic. - There are syntax errors (extra parentheses in method calls, malformed
printfstatements). - You need to compile the
.javafile to a.classfile first:
Open your terminal, navigate to the folder withClassWithTest.java, and run:javac ClassWithTest.java
Here's the corrected Java code:
public class ClassWithTest{ public ClassWithTest(){ System.out.println(insertLength("Tests ready to run")); } public void testAbs(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.println(insertLength("abs(-2) = 2: " + testResult(Math.abs(-2), 2))); System.out.println(insertLength("abs(-3) = -2: " + testResult(Math.abs(-3), -2))); } public void testRound(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.println(insertLength("round(0.7) = 1: " + testResult(Math.round(0.7), 1))); System.out.println(insertLength("round(0.2) = 1: " + testResult(Math.round(0.2), 1))); } public void testMin(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.println(insertLength("min(7,3) = 3: " + testResult(Math.min(7,3), 3))); System.out.println(insertLength("min(5,7) = 7: " + testResult(Math.min(5,7), 7))); } public void testMax(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.println(insertLength("max(7,14) = 14: " + testResult(Math.max(7,14), 14))); System.out.println(insertLength("max(5,7) = 5: " + testResult(Math.max(5,7), 5))); } public void TestDiv(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.println(insertLength("14 / 2 = 7: " + testResult(14 / 7, 3))); } public void testMult(int x){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.printf("2 * %d = %s%n", x, testResult(2 * x, 2 * x)); } public void otherTest(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); System.out.printf("1 = 1: %s%n", testResult(1, 1)); } // Make testAll public so Python can call it public void testAll(){ System.out.println(insertLength("Invocation of " + Thread.currentThread().getStackTrace()[1].getMethodName())); testAbs(); testRound(); testMin(); testMax(); } private static String testResult(double result, double expected){ return (result == expected ? "ok" : "no"); } public static String insertLength(Object obj){ String line = obj.toString(); return String.format("[%d]> %s", line.length(), line); } public static void main(String[] args){ new ClassWithTest().testAll(); } }
3. Corrected Python Code to Call Java & Log Output/Errors
Your original Python code had critical mistakes (wrong JVM path, missing classpath, incorrect method calls). Here's the fixed version that meets all your requirements:
import logging import jpype as jp from jpype import JClass, java # Configure error logging to write to ERROR.txt logging.basicConfig( filename="ERROR.txt", level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s" ) def main(): # Get the default JVM path (auto-detects your system's JVM) jvm_path = jp.getDefaultJVMPath() try: # Start JVM, add current directory to classpath (so it finds ClassWithTest.class) jp.startJVM( jvm_path, "-ea", "-Djava.class.path=.", convertStrings=False ) # Load the Java class ClassWithTest = JClass("ClassWithTest") # Redirect Java's System.out to OUTPUT.txt file_output = java.io.FileOutputStream("OUTPUT.txt") print_stream = java.io.PrintStream(file_output) java.lang.System.setOut(print_stream) # Create class instance and run tests test_instance = ClassWithTest() test_instance.testAll() # Clean up output stream print_stream.close() file_output.close() except Exception as e: # Log full error details (including stack trace) to ERROR.txt logging.error(str(e), exc_info=True) finally: # Ensure JVM always shuts down, even if an error occurs if jp.isJVMStarted(): jp.shutdownJVM() if __name__ == "__main__": main()
4. Key Things to Remember
- Classpath: Always add the directory with your compiled
.classfiles to the JVM's classpath (we used-Djava.class.path=.for the current directory). - JVM Shutdown: The
finallyblock ensures the JVM closes properly even if an error happens — this prevents leftover JVM processes. - Java Output Redirection: Using Java's own
System.setOut()is the most reliable way to capture all Java console output to a file. - Error Logging: Adding
exc_info=Truetologging.error()saves the full stack trace, which makes debugging way easier.
With these changes, you'll:
- Successfully call your Java class from Python 3
- Save all Java execution output to
OUTPUT.txt - Log any errors (JPype issues, Java exceptions) to
ERROR.txtbefore the program terminates
内容的提问来源于stack exchange,提问作者saharsa
相关产品推荐
相关产品推荐

