jep
jep copied to clipboard
matplotlib.pyplot.plot() not working with Jep (python 3.7.3)
The following code shows the issue calling matplotlib.pyplot.plot()
import jep.*;
public class JepIssue {
public static void main(String[] args) throws JepException {
// Jep Shared library should be linkable
Jep jep = new SharedInterpreter();
jep.eval("from java.lang import System" );
jep.eval("import sys" );
jep.eval("System.out.println('I am jep! sys.argv: '+str(sys.argv) )" );
jep.eval("import matplotlib.pyplot as plt");
jep.eval("plt.plot([1,2,3], [4,5,6])");
jep.eval("plt.show()");
}
}
It gives the following output/error
I am jep! argv: []
Exception in thread "main" jep.JepException: <class 'IndexError'>: list index out of range
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/tkinter/__init__.__init__(__init__.py:2018)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/backends/_backend_tk.new_figure_manager_given_figure(_backend_tk.py:1008)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/backend_bases.new_figure_manager(backend_bases.py:3218)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/pyplot.figure(pyplot.py:525)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/pyplot.gcf(pyplot.py:578)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/pyplot.gca(pyplot.py:935)
at /home/pizzonia/.pyenv/versions/3.7.3/lib/python3.7/site-packages/matplotlib/pyplot.plot(pyplot.py:2809)
at <string>.<module>(<string>:1)
at jep.Jep.eval(Native Method)
at jep.Jep.eval(Jep.java:507)
at JepIssue.main(JepIssue.java:10)
The problem seems to be related with the fact that sys.argv is an empty list when python is called as embedded interpreter by Jep.
In fact, in tkinter/init.py:2018 we find
baseName = os.path.basename(sys.argv[0])
which assumes len(sys.argv)>0. Is this a Jep or a tkinter issue?
Python doc about sys.argv says
If no script name was passed to the Python interpreter, argv[0] is the empty string.
which implicitly states that argv[0] should exists. Hence, I suppose this should be considered a Jep bug.
Workaround
After creating the interpreter, just executes the following.
jep.eval("import sys" );
jep.eval("sys.argv.append('')");
Details
- OS Platform, Distribution, and Version: Ubuntu 14.04
- Python Distribution and Version: CPython 3.7.3
- Java Distribution and Version: java-8-oracle build 1.8.0_91-b14
- Jep Version: 3.8.2
- Python packages used (e.g. numpy, pandas, tensorflow): matplotlib
Thank you for the link. Given the Python doc you linked to states it should be the empty string, I am inclined to agree. However, I am reluctant to change it as I don't know what side effects this would have on existing projects using Jep and CPython extensions.
There was a lot of discussion on #81 about sys.argv. We may want to revisit that for a 4.0 that breaks backwards API.
In the past the best solution seems to be to change the backend for matplotlib, see #115.
Another option is to use MainInterpreter.setSharedModulesArgv()
I'm not completely convinced we should change, I try to stick to being a wrapper around python embedded interpreters, and according to the python documentation they leave responsibility for argv to developers using the API, we just follow their example and leave it to developers using jep. Having said all that I don't see any actual harm in setting it to empty string by default.
Hi guys, I've been facing 2 similar issues with jep :
The first is that python modules are not being recognized :
Exception in thread "main" jep.JepException: <class 'ModuleNotFoundError'>: No module named 'pandas'
at
code :
public static void main(String[] args) throws JepException {
// Jep Shared library should be linkable
Jep jep = new SharedInterpreter();
jep.eval("from java.lang import System" );
jep.eval("import sys" );
jep.eval("System.out.println('Hello from Java ')" );
jep.eval("print('hello from Python')");
jep.eval("pays = {\"pays\": [\"France\", \"Tunisie\"]}");
jep.eval("import pandas as pd");
jep.eval("tab = pd.DataFrame(pays)");
jep.eval("print(tab)");
The second is even simple methods like jep.eval("print('hello from Python')") doesn't show anything in console (no errors), where the same jep.eval("System.out.println('Hello from Java ')" ) prints the message correctly, what I'm I missing ? my guess it's something related to PYTHONHOME maybe ?