2010-04-06 21 views
9

Sembra che mi manchi qualcosa.in esecuzione bytecode jython utilizzando java

Quando si utilizza Jython per eseguire il mio codice Python in Java, vengono generati file bytecode Java (test.py -> [email protected]).

Posso eseguire queste classi direttamente utilizzando java?

In altre parole, voglio fare questo:

$ java [email protected] [additional cp args] 

lavoro.

L'intento: scrivere codice Python e non dover dare via il codice sorgente.

risposta

3

Vedere FAQ - Embedding Jython.

noti che jythonc è no longer supported:

jythonc non gestisce i generatori ed è difficile da mettere a punto e migliorare. Il pensiero corrente è di aggiungere capabiliti a jython stesso per generare bytecode da file py ed eseguire quegli elementi compilati staticamente piuttosto che l'approccio di jythonc di rendere le classi Java che funzionano come il codice Python di base. Il pensiero corrente è la seguente:

  • classi Accendere Python in classi Java senza l'interfaccia Java o classe utilizzando le annotazioni di funzione per specificare le informazioni sul tipo Java statico
  • staticamente compilare classi proxy per le classi Python che estendono le classi Java
  • codice rimuovi dal nucleo che è lì solo per supportare jythonc

L'esempio suggerisce annotazione speciale per ogni metodo in una classe Python che deve essere vis bile da Java:

class Simple(object): 
    @java 
    def __init__(self): 

    @java(String, String) 
    def firstWord(self, param): 
    return param.split(' ')[0] 
0

Se la vostra unica preoccupazione sta distribuendo l'applicazione senza dare via la fonte, si potrebbe desiderare di guardare strumenti come cx_freeze e py2exe su Windows e py2app su Mac.

Questi strumenti hanno la capacità di compilare file .py in bytecode.

+0

Il compilatore di Pypy è probabilmente una scelta migliore da una prospettiva di offuscamento. Sfortunatamente, è molto difficile da usare. – Antimony

4

Ecco ciò che funziona per me:

test_p.py:

def foo(): 
    print 'test from Python' 

TestJ.java:

import org.python.core.PyFrame; 
import org.python.core.PyFunctionTable; 
import org.python.util.PythonInterpreter; 

public class TestJ 
{ 
    public static void main(String[] args) 
    { 
    final PythonInterpreter interpreter = new PythonInterpreter(); 

    interpreter.exec("import sys"); 

    try 
     { 
     final Class<?> clazz = Class.forName("test_p$py"); 

     final java.lang.reflect.Constructor constructor 
      = clazz.getConstructor(String.class); 

     final PyFunctionTable module = (PyFunctionTable)constructor.newInstance(""); 

     final java.lang.reflect.Method method 
      = clazz.getDeclaredMethod("foo$1", 
            PyFrame.class, 
            org.python.core.ThreadState.class); 

     method.invoke(module, 
         (PyFrame)interpreter.eval("sys._getframe()").__tojava__(PyFrame.class), 
         org.python.core.Py.getThreadState()); 
     } 
    catch (final ClassNotFoundException e) 
     { e.printStackTrace(); } 
    catch (final NoSuchMethodException e) 
     { e.printStackTrace(); } 
    catch (final InstantiationException e) 
     { e.printStackTrace(); } 
    catch (final IllegalAccessException e) 
     { e.printStackTrace(); } 
    catch (final java.lang.reflect.InvocationTargetException e) 
     { e.printStackTrace(); } 
    } 
} 

Compilare test_p.py in test_p $ py.class :

$JYTHON_HOME/jython $JYTHON_HOME/Lib/compileall.py . 

Sposta test_p.py fuori strada, per dimostrare che non viene utilizzato:

mkdir hidden 
mv test_p.py hidden/ 

Compile:

javac -cp $JYTHON_HOME/jython.jar TestJ.java 

prova:

java -cp $JYTHON_HOME/jython.jar:. TestJ 

uscita:

test from Python