I鈥檓 having an issue with wrapping open ai gym. I created a minimal reproducible example that demonstrates what I mean
#include <pybind11/embed.h>
namespace py = pybind11;
auto main() -> int {
auto interpreter = py::scoped_interpreter{};
auto gym = py::module::import("gym");
auto env = gym.attr("make")("CartPole-v0");
auto state = env.attr("reset")();
env.attr("render")();
return 0;
}
This will crash, however only if I try to call the render method. If I only ask for the current state and print that out everything seems to work fine.
libc++abi.dylib: terminating with uncaught exception of type pybind11::error_already_set: IndexError: list index out of range
At:
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/pyglet/window/__init__.py(560): __init__
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/pyglet/gl/__init__.py(208): _create_shadow_window
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/pyglet/window/__init__.py(1896): <module>
<frozen importlib._bootstrap>(219): _call_with_frames_removed
<frozen importlib._bootstrap_external>(728): exec_module
<frozen importlib._bootstrap>(677): _load_unlocked
<frozen importlib._bootstrap>(967): _find_and_load_unlocked
<frozen importlib._bootstrap>(983): _find_and_load
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/pyglet/gl/__init__.py(239): <module>
<frozen importlib._bootstrap>(219): _call_with_frames_removed
<frozen importlib._bootstrap_external>(728): exec_module
<frozen importlib._bootstrap>(677): _load_unlocked
<frozen importlib._bootstrap>(967): _find_and_load_unlocked
<frozen importlib._bootstrap>(983): _find_and_load
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/gym/envs/classic_control/rendering.py(25): <module>
<frozen importlib._bootstrap>(219): _call_with_frames_removed
<frozen importlib._bootstrap_external>(728): exec_module
<frozen importlib._bootstrap>(677): _load_unlocked
<frozen importlib._bootstrap>(967): _find_and_load_unlocked
<frozen importlib._bootstrap>(983): _find_and_load
<frozen importlib._bootstrap>(219): _call_with_frames_removed
<frozen importlib._bootstrap>(1043): _handle_fromlist
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/gym/envs/classic_control/cartpole.py(150): render
/Users/adamkowalski/miniconda3/lib/python3.7/site-packages/gym/core.py(244): render
The Python code for this works just fine when tried in the interpreter
import gym
env = gym.make("CartPole-v0")
state = env.reset()
env.render()
With the help of Yannick Jadoul we were able to resolve this issue and came to a very interesting conclusion. We need to set the argv of the python interpreter so that rather than being [] it should equal ['']. I have attached our conversation to understand the journey we went through to solve this problem!







Quick summary for later readers in a hurry:
sys.argv[0] if no caption is setPy_Initialize), sys.argv is an empty list, while sys.argv is [''] inside a Python interpreter.Py_initialize's documentation mentions "It does not set sys.argv; use PySys_SetArgvEx() for that."We came up with a few options on how to solve this:
['']initialize_interpreter that can take argv, making clear that calling the original overload does not set sys.argvI'll close this as it is not really a pybind11-specific issue.
@wjakob Actually, the fact that sys.argv is an empty list inside a pybind11 embedded interpreter might be a pybind11-specific issue? (Or at least something worth mentioning in the docs.)
I came across exactly the same problem using matplotlib/tkinter
adding
py::module::import("sys").attr("argv").attr("append")("")
solved the problem, as pointed out above.
I came across exactly the same problem using matplotlib/tkinter
adding
py::module::import("sys").attr("argv").attr("append")("")
solved the problem, as pointed out above.
I try to call python script modules from c++ using pybind11, but when using gui related functions (like tinker) in python file, it always give an exceptions about 'list index out of range'. As I looked into the exception line, and found out it was about empty sys.argv variable.
Though your code tip successfully avoids that exception, I really hope that pybind11 devs could give us a better solution.
Very useful. I followed this and it works for me
Most helpful comment
With the help of Yannick Jadoul we were able to resolve this issue and came to a very interesting conclusion. We need to set the
argvof the python interpreter so that rather than being[]it should equal['']. I have attached our conversation to understand the journey we went through to solve this problem!