1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gym.render() でDISPLAYのエラーが出たときの対処法

Posted at

困ったこと

dockerコンテナでOpen AI Gymのサンプルコードを実行しようとしたら、次のようなエラーメッセージが出てしまいました。

ターミナル
Traceback (most recent call last):
  File "hello_gym.py", line 8, in <module>
    env.render()
  File "/usr/local/lib/python3.6/dist-packages/gym/core.py", line 240, in render
    return self.env.render(mode, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/gym/envs/classic_control/cartpole.py", line 174, in render
    from gym.envs.classic_control import rendering
  File "/usr/local/lib/python3.6/dist-packages/gym/envs/classic_control/rendering.py", line 25, in <module>
    from pyglet.gl import *
  File "/usr/local/lib/python3.6/dist-packages/pyglet/gl/__init__.py", line 244, in <module>
    import pyglet.window
  File "/usr/local/lib/python3.6/dist-packages/pyglet/window/__init__.py", line 1880, in <module>
    gl._create_shadow_window()
  File "/usr/local/lib/python3.6/dist-packages/pyglet/gl/__init__.py", line 220, in _create_shadow_window
    _shadow_window = Window(width=1, height=1, visible=False)
  File "/usr/local/lib/python3.6/dist-packages/pyglet/window/xlib/__init__.py", line 165, in __init__
    super(XlibWindow, self).__init__(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/pyglet/window/__init__.py", line 570, in __init__
    display = pyglet.canvas.get_display()
  File "/usr/local/lib/python3.6/dist-packages/pyglet/canvas/__init__.py", line 94, in get_display
    return Display()
  File "/usr/local/lib/python3.6/dist-packages/pyglet/canvas/xlib.py", line 123, in __init__
    raise NoSuchDisplayException('Cannot connect to "%s"' % name)
pyglet.canvas.xlib.NoSuchDisplayException: Cannot connect to "None"

実行環境

実行環境は次のとおりです。

バージョン
OS Ubuntu18.04
python 3.6
gym 0.18.0
pyglet 1.5.0
xvfb 2:1.19.6
x11vnc 0.9.13

Ubintu18.04ベースのdockerコンテナにvncを設定して、render()の出力結果をブラウザで確認しようとしています。

考えたこと

  • VNCの設定ができていない
  • X displayの設定ができていない
  • gymサンプルコードのエラー(render周り)
  • pygletのバージョンが合っていない(pygletは最新を入れていました)

gymのサンプルコードは次のとおりです。

sample.py
import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample()) # take a random action
env.close()

(実はこのコードは、別の理由でエラーが起こるのですが、それはまた別の記事で…)

原因

DISPLAYの設定ができていませんでした。

ターミナルで環境変数を確認します。

ターミナル
$ printenv

一覧がずらずらっと表示されて

ターミナル
LANG=C.UTF-8
OLDPWD=/home/user
VISIBLE=now
USER=user
PWD=/home/user/workspace
HOME=/home/user
略

DISPLAY=の表示がありません。設定したはずなのに…。

DISPLAY 環境変数の設定 (うまくいかなかった例)

次の3つの方法は試しましたが、うまくいきませんでした。
解決策を早く知りたい方はジャンプ

設定法1

もともとはDockerfileの中で設定していました(できているつもりでした)

Dockerfile
ENV DISPLAY=:0

でも、コンテナ内の環境変数は設定できていませんでした。

設定法2 docker runのオプションで設定する

次に試したのがこの方法。

ターミナル
docker run -e DISPLAY=$DISPLAY 以下略

ちなみに、-e--envに変えても、だめでした笑

設定法3 startup.shで設定する

startup.shは、ざっくり言うとコンテナを起動する際に、実行させることのできるシェルスクリプトです。
(よくわかっていないだけw)

Dockerfileの最後にCMD命令を記述できますが、複数のコマンドを実行させたい場合に、
それらをstartup.shの中に記述することで実行させます。

Dockerfile
CMD ["/startup.sh"]

なぜstartup.shを使ったかというと、sshvncsupervisordによって起動させたかったので、/usr/bin/supervisord -c /etc/supervisor/supervisord.confは少なくともbashで実行する必要があったからです。
そのため、コマンドを2行記述しました。

startup.sh
#!/bin/bash
/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
export DISPLAY=:0

結局この方法でも、エラーは解決しませんでした。

解決策

Dockerfileの中で次のように記述します。

RUN echo "export DISPLAY=:0"  >> /etc/profile

これで、コンテナ内の環境変数にDISPLAYを設定することができました。

まとめ

dockerコンテナ内でgymを実行した際にpyglet.canvas.xlib.NoSuchDisplayException: Cannot connect to "None"というエラーが表示されたら、
DISPLAYの環境変数が設定できていないかもしれません。

Dockerfile内でRUN echo "export DISPLAY=:0" >> /etc/profileと実行すると設定できました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?