[077a87]: / osim / http / client.py

Download this file

109 lines (96 with data), 4.1 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
# ADAPTED FROM https://github.com/openai/gym-http-api
import requests
import six.moves.urllib.parse as urlparse
import json
import os
import pkg_resources
import sys
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class Client(object):
"""
Gym client to interface with gym_http_server
"""
def __init__(self, remote_base):
self.remote_base = remote_base
self.session = requests.Session()
self.session.headers.update({'Content-type': 'application/json'})
self.instance_id = None
def _parse_server_error_or_raise_for_status(self, resp):
j = {}
try:
j = resp.json()
except:
# Most likely json parse failed because of network error, not server error (server
# sends its errors in json). Don't let parse exception go up, but rather raise default
# error.
resp.raise_for_status()
if resp.status_code != 200 and "message" in j: # descriptive message from server side
raise ServerError(message=j["message"], status_code=resp.status_code)
resp.raise_for_status()
return j
def _post_request(self, route, data):
url = urlparse.urljoin(self.remote_base, route)
logger.info("POST {}\n{}".format(url, json.dumps(data)))
resp = self.session.post(urlparse.urljoin(self.remote_base, route),
data=json.dumps(data))
return self._parse_server_error_or_raise_for_status(resp)
def _get_request(self, route):
url = urlparse.urljoin(self.remote_base, route)
logger.info("GET {}".format(url))
resp = self.session.get(url)
return self._parse_server_error_or_raise_for_status(resp)
def env_create(self, token, env_id = "Run"):
route = '/v1/envs/'
data = {'env_id': env_id,
'token': token,
'version': pkg_resources.get_distribution("osim-rl").version }
try:
resp = self._post_request(route, data)
except ServerError as e:
sys.exit(e.message)
self.instance_id = resp['instance_id']
self.env_monitor_start("tmp", force=True)
return self.env_reset()
def env_reset(self):
route = '/v1/envs/{}/reset/'.format(self.instance_id)
resp = self._post_request(route, None)
observation = resp['observation']
return observation
def env_step(self, action, render=False):
route = '/v1/envs/{}/step/'.format(self.instance_id)
data = {'action': action, 'render': render}
resp = self._post_request(route, data)
observation = resp['observation']
reward = resp['reward']
done = resp['done']
info = resp['info']
return [observation, reward, done, info]
def env_monitor_start(self, directory,
force=False, resume=False, video_callable=False):
route = '/v1/envs/{}/monitor/start/'.format(self.instance_id)
data = {'directory': directory,
'force': force,
'resume': resume,
'video_callable': video_callable}
self._post_request(route, data)
def submit(self):
route = '/v1/envs/{}/monitor/close/'.format(self.instance_id)
result = self._post_request(route, None)
if result['reward']:
print("Your total reward from this submission: %f" % result['reward'])
else:
print("There was an error in your submission. Please contact administrators.")
route = '/v1/envs/{}/close/'.format(self.instance_id)
self.env_close()
def env_close(self):
route = '/v1/envs/{}/close/'.format(self.instance_id)
self._post_request(route, None)
class ServerError(Exception):
def __init__(self, message, status_code=None):
Exception.__init__(self)
print('ServerErrorPrint',message,status_code)
self.message = message
if status_code is not None:
self.status_code = status_code