Pybind11: Cannot render open ai gym environment

Created on 13 Apr 2019  路  7Comments  路  Source: pybind/pybind11

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()

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 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!

Screen Shot 2019-04-13 at 3 46 32 PM

Screen Shot 2019-04-13 at 3 46 41 PM

Screen Shot 2019-04-13 at 3 46 51 PM

Screen Shot 2019-04-13 at 3 47 00 PM

Screen Shot 2019-04-13 at 3 47 09 PM

Screen Shot 2019-04-13 at 3 47 17 PM

Screen Shot 2019-04-13 at 3 47 25 PM

All 7 comments

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!

Screen Shot 2019-04-13 at 3 46 32 PM

Screen Shot 2019-04-13 at 3 46 41 PM

Screen Shot 2019-04-13 at 3 46 51 PM

Screen Shot 2019-04-13 at 3 47 00 PM

Screen Shot 2019-04-13 at 3 47 09 PM

Screen Shot 2019-04-13 at 3 47 17 PM

Screen Shot 2019-04-13 at 3 47 25 PM

Quick summary for later readers in a hurry:

  • Open AI gym accesses sys.argv[0] if no caption is set
  • When embedding the interpreter with pybind11 (i.e., through a call to Py_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:

  • Do nothing but make a note in the docs
  • Always set to ['']
  • Make an overload of initialize_interpreter that can take argv, making clear that calling the original overload does not set sys.argv

I'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

Was this page helpful?
0 / 5 - 0 ratings