我正在用Java构建一个框架,它将监听事件,然后在Jython中处理它们。不同的事件类型将被发送到不同的脚本。
由于在调用PythonInterpreter.exec()时jython需要相当长的时间来编译脚本,因此我必须预编译脚本。我是按照以下方式做的:
// initialize the script as string (would load it from file in final version)
String script = "print 'foo'";
// get the compiled code object
PyCode compiled = org.python.core.__builtin__.compile( script, "<>", "exec" );
PyCode编译对象将被推送到存储库并用作事件进入
PythonInterpreter pi = new PythonInterpreter();
pi.set( "variable_1", "value_1");
pi.set( "variable_x", "value_x");
pi.exec( compiled );
现在我的难题 - 可能会发生某些类型的多个事件同时发生 - 因此同时运行多个脚本实例。
几乎所有脚本都可能保持短暂 - 最多100行,没有循环。数字和频率是完全随机的(用户生成的事件),每个事件类型可以是每秒0到约200个。
最好的方法是什么?我正在寻找一些可能性:
2号和3号的组合可能是最好的 - 创建动态池大小?
那么,有什么想法吗? ;)
答案 0 :(得分:3)
遗憾的是PyCode
实例不是不可变的(类上有很多公共成员)。
您可以使用以下代码预编译可重用的脚本:
// TODO: generate this name
final String name = "X";
byte[] scriptBytes = PyString.to_bytes(script);
CompilerFlags flags = Py.getCompilerFlags();
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
Module.compile(parser.parse(new ByteArrayInputStream(scriptBytes), "exec",
"<>", flags), ostream, name, "<>", false, false, false, flags);
byte[] buffer = ostream.toByteArray();
Class<PyRunnable> clazz = BytecodeLoader.makeClass(name, null, buffer);
final Constructor<PyRunnable> constructor = clazz
.getConstructor(new Class[] { String.class });
然后,您可以使用构造函数在需要时为脚本生成PyCode实例:
PyRunnable r = constructor.newInstance(name);
PyCode pc = r.getMain();
我是第一个承认这不是一个很好的做事方式的人,并且可能说明了我对Jython缺乏经验。但是,它比每次编译要快得多。代码在Jython 2.2.1下运行,但不会在Jython 2.5下编译(也不会在你的代码下编译)。
答案 1 :(得分:1)
PythonInterpreter很昂贵,这段代码只使用一个。
#action.py
def execute(filename, action_locals):
#add caching of compiled scripts here
exec(compile(open(filename).read(), filename, 'exec'), action_locals)
//class variable, only one interpreter
PythonInterpreter pi;
//run once in init() or constructor
pi = new PythonInterpreter();//could do more initialization here
pi.exec("import action");
//every script execution
PyObject pyActionRunner = pi.eval("action.execute");
PyString pyActionName = new PyString(script_path);
PyDictionary pyActionLocals = new PyDictionary();
pyActionLocals.put("variable_1", "value_1");
pyActionLocals.put("variable_x", "value_x")
pyActionRunner.__call__(pyActionName, pyActionLocals);
#example_script.py
print variable_1, variable_x