diff --git a/liteflow-script-plugin/liteflow-script-python/pom.xml b/liteflow-script-plugin/liteflow-script-python/pom.xml
index 311ba8d96..5ab16e68b 100644
--- a/liteflow-script-plugin/liteflow-script-python/pom.xml
+++ b/liteflow-script-plugin/liteflow-script-python/pom.xml
@@ -24,5 +24,4 @@
jython-standalone
-
\ No newline at end of file
diff --git a/liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java b/liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java
index b6fc46a91..9ceb333df 100644
--- a/liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java
+++ b/liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java
@@ -3,39 +3,120 @@ package com.yomahub.liteflow.script.python;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.enums.ScriptTypeEnum;
-import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
-import java.util.Arrays;
-import java.util.List;
+import com.yomahub.liteflow.script.ScriptExecuteWrap;
+import com.yomahub.liteflow.script.ScriptExecutor;
+import com.yomahub.liteflow.script.exception.ScriptLoadException;
+import org.python.core.PyCode;
+import org.python.core.PyObject;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+import java.util.*;
import java.util.stream.Collectors;
/**
* Python脚本语言的执行器实现
*
* @author Bryan.Zhang
- * @since 2.9.5
+ * @since 2.12.0
*/
-public class PythonScriptExecutor extends JSR223ScriptExecutor {
+public class PythonScriptExecutor extends ScriptExecutor {
- @Override
- public ScriptTypeEnum scriptType() {
- return ScriptTypeEnum.PYTHON;
- }
+ private PythonInterpreter pythonInterpreter;
- @Override
- protected String convertScript(String script) {
- String[] lineArray = script.split("\\n");
- List noBlankLineList = Arrays.stream(lineArray)
- .filter(s -> !StrUtil.isBlank(s))
- .collect(Collectors.toList());
+ private final String RESULT_KEY = "result";
- // 用第一行的缩进的空格数作为整个代码的缩进量
- String blankStr = ReUtil.getGroup0("^[ ]*", noBlankLineList.get(0));
+ private final Map compiledScriptMap = new HashMap<>();
- // 重新构建脚本
- StringBuilder scriptSB = new StringBuilder();
- noBlankLineList.forEach(s -> scriptSB.append(StrUtil.format("{}\n", s.replaceFirst(blankStr, StrUtil.EMPTY))));
- return scriptSB.toString();
- }
+ @Override
+ public ScriptExecutor init(){
+ PySystemState systemState = new PySystemState();
+ systemState.setdefaultencoding("UTF-8");
+ this.pythonInterpreter = new PythonInterpreter(null, systemState);
+ return this;
+ }
+ @Override
+ public void load(String nodeId, String script) {
+ try {
+ PyCode pyCode = (PyCode) compile(script);
+ compiledScriptMap.put(nodeId, pyCode);
+ }
+ catch (Exception e) {
+ String errorMsg = StrUtil.format("script loading error for node[{}],error msg:{}", nodeId, e.getMessage());
+ throw new ScriptLoadException(errorMsg);
+ }
+ }
+
+ @Override
+ public void unLoad(String nodeId) {
+ compiledScriptMap.remove(nodeId);
+ }
+
+ @Override
+ public List getNodeIds() {
+ return new ArrayList<>(compiledScriptMap.keySet());
+ }
+
+ @Override
+ public Object executeScript(ScriptExecuteWrap wrap) throws Exception {
+ if (!compiledScriptMap.containsKey(wrap.getNodeId())) {
+ String errorMsg = StrUtil.format("script for node[{}] is not loaded", wrap.getNodeId());
+ throw new ScriptLoadException(errorMsg);
+ }
+
+ PyCode compiledScript = compiledScriptMap.get(wrap.getNodeId());
+
+ bindParam(wrap, pythonInterpreter::set, pythonInterpreter::set);
+
+ pythonInterpreter.exec(compiledScript);
+
+ PyObject result = pythonInterpreter.get(RESULT_KEY);
+
+ if (result == null){
+ return null;
+ }
+
+ pythonInterpreter.cleanup();
+
+ switch (wrap.getCmp().getType()){
+ case BOOLEAN_SCRIPT:
+ return result.__tojava__(Boolean.class);
+ case FOR_SCRIPT:
+ return result.__tojava__(Integer.class);
+ default:
+ return result.__tojava__(Object.class);
+ }
+ }
+
+ @Override
+ public void cleanCache() {
+ compiledScriptMap.clear();
+ }
+
+ @Override
+ public ScriptTypeEnum scriptType() {
+ return ScriptTypeEnum.PYTHON;
+ }
+
+ @Override
+ public Object compile(String script) throws Exception {
+ return pythonInterpreter.compile(convertScript(script));
+ }
+
+ private String convertScript(String script) {
+ String[] lineArray = script.split("\\n");
+ List noBlankLineList = Arrays.stream(lineArray)
+ .filter(s -> !StrUtil.isBlank(s))
+ .collect(Collectors.toList());
+
+ // 用第一行的缩进的空格数作为整个代码的缩进量
+ String blankStr = ReUtil.getGroup0("^[ ]*", noBlankLineList.get(0));
+
+ // 重新构建脚本
+ StringBuilder scriptSB = new StringBuilder();
+ noBlankLineList.forEach(s -> scriptSB.append(StrUtil.format("{}\n", s.replaceFirst(blankStr, StrUtil.EMPTY))));
+
+ return scriptSB.toString().replace("return", RESULT_KEY + "=");
+ }
}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/common/ScriptPythonCommonELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/common/ScriptPythonCommonELTest.java
index a29b63fbe..a21420d23 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/common/ScriptPythonCommonELTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/common/ScriptPythonCommonELTest.java
@@ -39,8 +39,9 @@ public class ScriptPythonCommonELTest extends BaseTest {
DefaultContext context = response.getFirstContextBean();
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals(Integer.valueOf(30), context.getData("s1"));
- Assertions.assertEquals("杰克", context.getData("name"));
+ Assertions.assertEquals("jack", context.getData("name"));
Assertions.assertEquals("hi,jack", context.getData("td"));
+ Assertions.assertEquals("中文",context.getData("s2"));
}
@Test