All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.python.util.PythonInterpreter Maven / Gradle / Ivy

Go to download

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.

There is a newer version: 2.7.4
Show newest version
package org.python.util;

import java.io.Closeable;
import java.io.Reader;
import java.io.StringReader;
import java.util.Properties;

import org.python.antlr.base.mod;
import org.python.core.CodeFlag;
import org.python.core.CompileMode;
import org.python.core.CompilerFlags;
import org.python.core.Options;
import org.python.core.ParserFacade;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyException;
import org.python.core.PyFile;
import org.python.core.PyFileReader;
import org.python.core.PyFileWriter;
import org.python.core.PyModule;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.core.__builtin__;

/**
 * The PythonInterpreter class is a standard wrapper for a Jython interpreter for embedding in a
 * Java application.
 */
public class PythonInterpreter implements AutoCloseable, Closeable {

    // Defaults if the interpreter uses thread-local state
    protected PySystemState systemState;
    PyObject globals;

    protected final boolean useThreadLocalState;

    protected static ThreadLocal threadLocals = new ThreadLocal() {

        @Override
        protected Object[] initialValue() {
            return new Object[1];
        }
    };

    protected CompilerFlags cflags = new CompilerFlags();

    private volatile boolean closed = false;

    /**
     * Initializes the Jython runtime. This should only be called once, before any other Python
     * objects (including PythonInterpreter) are created.
     *
     * @param preProperties A set of properties. Typically System.getProperties() is used.
     *            preProperties override properties from the registry file.
     * @param postProperties Another set of properties. Values like python.home, python.path and all
     *            other values from the registry files can be added to this property set.
     *            postProperties override system properties and registry properties.
     * @param argv Command line arguments, assigned to sys.argv.
     */
    public static void
            initialize(Properties preProperties, Properties postProperties, String[] argv) {
        PySystemState.initialize(preProperties, postProperties, argv);
    }

    /**
     * Creates a new interpreter with an empty local namespace.
     */
    public PythonInterpreter() {
        this(null, null);
    }

    /**
     * Creates a new interpreter with the ability to maintain a separate local namespace for each
     * thread (set by invoking setLocals()).
     *
     * @param dict a Python mapping object (e.g., a dictionary) for use as the default namespace
     */
    public static PythonInterpreter threadLocalStateInterpreter(PyObject dict) {
        return new PythonInterpreter(dict, new PySystemState(), true);
    }

    /**
     * Creates a new interpreter with a specified local namespace.
     *
     * @param dict a Python mapping object (e.g., a dictionary) for use as the namespace
     */
    public PythonInterpreter(PyObject dict) {
        this(dict, null);
    }

    public PythonInterpreter(PyObject dict, PySystemState systemState) {
        this(dict, systemState, false);
    }

    protected PythonInterpreter(PyObject dict, PySystemState systemState,
            boolean useThreadLocalState) {

        globals = dict != null ? dict : Py.newStringMap();
        this.systemState = systemState != null ? systemState : Py.getSystemState();
        setSystemState();

        this.useThreadLocalState = useThreadLocalState;
        if (!useThreadLocalState) {
            PyModule module = new PyModule("__main__", globals);
            this.systemState.modules.__setitem__("__main__", module);
        }

        if (Options.Qnew) {
            cflags.setFlag(CodeFlag.CO_FUTURE_DIVISION);
        }

        Py.importSiteIfSelected();
    }

    public PySystemState getSystemState() {
        return systemState;
    }

    protected void setSystemState() {
        Py.setSystemState(getSystemState());
    }

    /**
     * Sets a Python object to use for the standard input stream, sys.stdin. This
     * stream is used in a byte-oriented way, through calls to read and
     * readline on the object.
     *
     * @param inStream a Python file-like object to use as the input stream
     */
    public void setIn(PyObject inStream) {
        getSystemState().stdin = inStream;
    }

    /**
     * Sets a {@link Reader} to use for the standard input stream, sys.stdin. This
     * stream is wrapped such that characters will be narrowed to bytes. A character greater than
     * U+00FF will raise a Java IllegalArgumentException from within
     * {@link PyString}.
     *
     * @param inStream to use as the input stream
     */
    public void setIn(java.io.Reader inStream) {
        setIn(new PyFileReader(inStream));
    }

    /**
     * Sets a {@link java.io.InputStream} to use for the standard input stream.
     *
     * @param inStream InputStream to use as input stream
     */
    public void setIn(java.io.InputStream inStream) {
        setIn(new PyFile(inStream));
    }

    /**
     * Sets a Python object to use for the standard output stream, sys.stdout. This
     * stream is used in a byte-oriented way (mostly) that depends on the type of file-like object.
     * The behaviour as implemented is:
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
     * 
Stream behaviour for various object types
Python type of object o written
str/bytesunicodeAny other type
{@link PyFile}as bytes directlyrespect {@link PyFile#encoding}call str(o) first
{@link PyFileWriter}each byte value as a charwrite as Java charscall o.toString() first
Other {@link PyObject} finvoke f.write(str(o))invoke f.write(o)invoke f.write(str(o))
* * @param outStream Python file-like object to use as the output stream */ public void setOut(PyObject outStream) { getSystemState().stdout = outStream; } /** * Sets a {@link java.io.Writer} to use for the standard output stream, sys.stdout. * The behaviour as implemented is to output each object o by calling * o.toString() and writing this as UTF-16. * * @param outStream to use as the output stream */ public void setOut(java.io.Writer outStream) { setOut(new PyFileWriter(outStream)); } /** * Sets a {@link java.io.OutputStream} to use for the standard output stream. * * @param outStream OutputStream to use as output stream */ public void setOut(java.io.OutputStream outStream) { setOut(new PyFile(outStream)); } /** * Sets a Python object to use for the standard output stream, sys.stderr. This * stream is used in a byte-oriented way (mostly) that depends on the type of file-like object, * in the same way as {@link #setOut(PyObject)}. * * @param outStream Python file-like object to use as the error output stream */ public void setErr(PyObject outStream) { getSystemState().stderr = outStream; } /** * Sets a {@link java.io.Writer} to use for the standard output stream, sys.stdout. * The behaviour as implemented is to output each object o by calling * o.toString() and writing this as UTF-16. * * @param outStream to use as the error output stream */ public void setErr(java.io.Writer outStream) { setErr(new PyFileWriter(outStream)); } public void setErr(java.io.OutputStream outStream) { setErr(new PyFile(outStream)); } /** * Evaluates a string as a Python expression and returns the result. */ public PyObject eval(String s) { setSystemState(); return __builtin__.eval(new PyString(s), getLocals()); } /** * Evaluates a Python code object and returns the result. */ public PyObject eval(PyObject code) { setSystemState(); return __builtin__.eval(code, getLocals()); } /** * Executes a string of Python source in the local namespace. * * In some environments, such as Windows, Unicode characters in the script will be converted * into ascii question marks (?). This can be avoided by first compiling the fragment using * PythonInterpreter.compile(), and using the overridden form of this method which takes a * PyCode object. Code page declarations are not supported. */ public void exec(String s) { setSystemState(); Py.exec(Py.compile_flags(s, "", CompileMode.exec, cflags), getLocals(), null); Py.flushLine(); } /** * Executes a Python code object in the local namespace. */ public void exec(PyObject code) { setSystemState(); Py.exec(code, getLocals(), null); Py.flushLine(); } /** * Executes a file of Python source in the local namespace. */ public void execfile(String filename) { PyObject locals = getLocals(); setSystemState(); __builtin__.execfile_flags(filename, locals, locals, cflags); Py.flushLine(); } public void execfile(java.io.InputStream s) { execfile(s, ""); } public void execfile(java.io.InputStream s, String name) { setSystemState(); Py.runCode(Py.compile_flags(s, name, CompileMode.exec, cflags), null, getLocals()); Py.flushLine(); } /** * Compiles a string of Python source as either an expression (if possible) or a module. * * Designed for use by a JSR 223 implementation: "the Scripting API does not distinguish between * scripts which return values and those which do not, nor do they make the corresponding * distinction between evaluating or executing objects." (SCR.4.2.1) */ public PyCode compile(String script) { return compile(script, "