在Scala程序中嵌入Jython

时间:2017-12-02 12:54:47

标签: scala jython

我想在Scala程序中嵌入Jython解释器。但是,我无法获得脚本引擎。

我正在使用SBT v0.13.15。这是我的build.sbt文件:

name := "jython"

version := "0.1"

scalaVersion := "2.11.11"

libraryDependencies ++= Seq(
  "org.python" % "jython" % "2.7.0",
  "org.scala-lang" % "scala-compiler" % scalaVersion.value
)

我的Scala代码是

package forms

import javax.script._

object Main {
  def main(args: Array[String]): Unit = {
    val engineManager = new ScriptEngineManager()
    for (i ← 0 until engineManager.getEngineFactories.size()) {
      val e = engineManager.getEngineFactories.get(i)
      println(s"factory name: ${e.getEngineName}, ${e.getLanguageName}, ${e.getNames}")
    }

    val engine = engineManager.getEngineByName("python")
    require(engine != null, "Script engine is null.")
  }
}

此输出

factory name: Scala Interpreter, Scala, [scala]
factory name: Oracle Nashorn, ECMAScript, [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]
factory name: jython, python, [python, jython]
Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: Script engine is null.

所以看起来引擎管理器知道python工厂但是无法“获取”它或实例化它。我尝试使用名称“python”和“jython”访问它,结果类似。

我已经阅读here,将null传递给ScriptEngineManager会有所帮助,但对我来说这是倒退了一步。它只找到了nashorn工厂。

我也试过直接实例化python工厂:

val engine = (new PyScriptEngineFactory).getScriptEngine

但这会产生一个错误,看起来正在取得进展,但我不知道如何解决:

Exception in thread "main" ImportError: Cannot import site module and its dependencies: No module named site
Determine if the following attributes are correct:
  * sys.path: ['/Users/bwbecker/.ivy2/cache/org.python/jython/jars/Lib', '__classpath__', '__pyclasspath__/']
    This attribute might be including the wrong directories, such as from CPython
  * sys.prefix: /Users/bwbecker/.ivy2/cache/org.python/jython/jars
    This attribute is set by the system property python.home, although it can
    be often automatically determined by the location of the Jython jar file

我推测这两种方法可能有同样的根本问题。第一种方法只是捕获初始化错误并返回null。

欢迎任何有关如何进行的建议。

1 个答案:

答案 0 :(得分:1)

您可以通过在调用获取引擎之前放置以下代码来抑制导入站点模块的尝试(使用EngineManager或直接使用PyScriptEngineFactory):

import org.python.core.Py
import org.python.core.PySystemState

val props = new Properties()
props.setProperty("python.import.site", "false")
PySystemState.initialize(props, new Properties())
val engineSys = new PySystemState
Py.setSystemState(engineSys)