Hi Andi, Please find attached the patch that adds the eval to JCC.
It uses PyRun_SimpleString which returns 0 or -1, I have verified it works, on errors it returns -1, unless one sends "raise SystemException()" -- then it tears down all VMs For better reporting I'd have to use http://docs.python.org/c-api/veryhigh.html#PyRun_String Could you give me some pointers on how to obtain *globals *locals parameters? I can modify the patch to use PyRun_String (it would be nice to have the exceptions -- i think that exceptions will be reported automatically when the native method is declared as throwing them) something like...? PyObject *module = PyImport_ImportModule("__builtin__"); PyObject *globalFunction = PyObject_GetAttrString(module, "globals"); PyObject *globals = *PyObject_CallFunction(globalFunction, NULL); Thanks, Roman On Mon, Nov 14, 2011 at 6:12 PM, Andi Vajda <va...@apache.org> wrote: > > Hi Roman, > > On Mon, 14 Nov 2011, Roman Chyla wrote: > >> so after reading >> http://docs.python.org/c-api/init.html#PySys_SetArgvEx and the source >> code for _PythonVM_init i figured it out >> >> I have to do: >> >> PythonVM.start("/dvt/workspace/montysolr/src/python/montysolr"); >> >> and the sys.path then contains the parent folder (above montysolr) and >> i can then set more things by loading some boostrap module >> >> but something like >> http://docs.python.org/c-api/veryhigh.html#PyRun_SimpleString would be >> much more flexible. Is it something that could be added? I can prepare >> a patch (as it seems really trivial my knowledge might be sufficient >> for this :)) > > Yes, adding an 'eval' method on PythonVM, like the 'instantiate' method, > would make sense. A patch is welcome ! > > Andi.. > >> >> roman >> >> On Mon, Nov 14, 2011 at 1:12 PM, Roman Chyla <roman.ch...@gmail.com> >> wrote: >>> >>> On Mon, Nov 14, 2011 at 4:25 AM, Andi Vajda <va...@apache.org> wrote: >>>> >>>> On Sun, 13 Nov 2011, Roman Chyla wrote: >>>> >>>>> I am using JCC to run Python inside Java. For unittest, I'd like to >>>>> set PYTHONPATH environment variable programmatically. I can change env >>>>> vars inside Java (using >>>>> >>>>> >>>>> http://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java) >>>>> and System.getenv("PYTHONPATH") shows correct values >>>>> >>>>> However, I am still getting "ImportError: no module named...." >>>>> >>>>> If I set PYTHONPATH before starting unittest, it works fine >>>>> >>>>> Is it possible what I would like to do? >>>> >>>> Why mess with the environment instead of setting sys.path directly >>>> instead ? >>> >>> That would be great, but I don't know how. I am doing roughly this: >>> >>> PythonVM.start(programName) >>> vm = PythonVM.get() >>> vm.instantiate(moduleName, className); >>> >>> I tried also: >>> PythonVM.start(programName, new String[]{"-c", "import >>> sys;sys.path.insert(0, \'/dvt/workspace/montysolr/src/python\'"}); >>> >>> it is failing on vm.instantiate.... when Python cannot find the module >>> >>>> >>>>> Alternatively, if JCC could execute/eval python string, I could set >>>>> sys.argv that way >>>> >>>> I'm not sure what you mean here but JCC's Java PythonVM.init() method >>>> takes >>>> an array of strings that is fed into sys.argv. See _PythonVM_Init() >>>> sources >>>> in jcc.cpp for details. >>> >>> sorry, i meant sys.path, not sys.argv >>> >>> roman >>> >>>> >>>> Andi.. >>>> >>> >> >
Index: jcc/sources/jcc.cpp =================================================================== --- jcc/sources/jcc.cpp (revision 1201881) +++ jcc/sources/jcc.cpp (working copy) @@ -602,6 +602,20 @@ return jobj; } + +static jint _PythonVM_eval(JNIEnv *vm_env, jobject self, + jstring pythonCommand) +{ + PythonGIL gil(vm_env); + + const char *pyStr = vm_env->GetStringUTFChars(pythonCommand, JNI_FALSE); + jint ret = PyRun_SimpleString((char *) pyStr); + vm_env->ReleaseStringUTFChars(pythonCommand, pyStr); + + return ret; +} + + extern "C" { JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) @@ -626,6 +640,13 @@ return _PythonVM_instantiate(vm_env, self, moduleName, className); } + + JNIEXPORT jint JNICALL Java_org_apache_jcc_PythonVM_eval(JNIEnv *vm_env, jobject self, jstring pythonCommand) + { + return _PythonVM_eval(vm_env, self, pythonCommand); + } + + JNIEXPORT jint JNICALL Java_org_apache_jcc_PythonVM_acquireThreadState(JNIEnv *vm_env) { PyGILState_STATE state = PyGILState_Ensure(); Index: java/org/apache/jcc/PythonVM.java =================================================================== --- java/org/apache/jcc/PythonVM.java (revision 1201881) +++ java/org/apache/jcc/PythonVM.java (working copy) @@ -109,4 +109,11 @@ * than zero signals an error. */ public native int releaseThreadState(); + + /** + * Evaluates the string using python exec() call, it returns 0 on + * success and -1 on error. No exception is raised. If there was an + * unchecked SystemExit exception, the VM is likely destroyed + */ + public native int eval(String pythonCommand); }