remove six and __future__ imports
diff --git a/README.rst b/README.rst
index 8b778662f73..4fec59b8648 100644
--- a/README.rst
+++ b/README.rst
@@ -48,7 +48,7 @@ should know:
 Supported systems
 -----------------
 
-We currently support Linux and OS X running Python 2.7 or 3.5 -- 3.7. 
+We currently support Linux and OS X running Python 3.5 -- 3.8
 Windows support is experimental - algorithmic, toy_text, classic_control and atari *should* work on Windows (see next section for installation instructions); nevertheless, proceed at your own risk.
 
 Installation
diff --git a/examples/agents/cem.py b/examples/agents/cem.py
index e76c4b9335e..6a7332ee7c2 100644
--- a/examples/agents/cem.py
+++ b/examples/agents/cem.py
@@ -1,9 +1,7 @@
-from __future__ import print_function
-
 import gym
 from gym import wrappers, logger
 import numpy as np
-from six.moves import cPickle as pickle
+import pickle
 import json, sys, os
 from os import path
 from _policies import BinaryActionLinearPolicy # Different file so it can be unpickled
diff --git a/examples/agents/keyboard_agent.py b/examples/agents/keyboard_agent.py
index 71142871804..7a24b05f0b3 100644
--- a/examples/agents/keyboard_agent.py
+++ b/examples/agents/keyboard_agent.py
@@ -1,6 +1,4 @@
 #!/usr/bin/env python
-from __future__ import print_function
-
 import sys, gym, time
 
 #
diff --git a/gym/envs/algorithmic/algorithmic_env.py b/gym/envs/algorithmic/algorithmic_env.py
index 4a7ed75368c..35da87a8dfc 100644
--- a/gym/envs/algorithmic/algorithmic_env.py
+++ b/gym/envs/algorithmic/algorithmic_env.py
@@ -36,7 +36,7 @@
 import sys
 from contextlib import closing
 import numpy as np
-from six import StringIO
+from io import StringIO
 
 
 class AlgorithmicEnv(Env):
diff --git a/gym/envs/algorithmic/duplicated_input.py b/gym/envs/algorithmic/duplicated_input.py
index a6cc86e927e..18d06f255a0 100644
--- a/gym/envs/algorithmic/duplicated_input.py
+++ b/gym/envs/algorithmic/duplicated_input.py
@@ -2,7 +2,6 @@
 Task is to return every nth character from the input tape.
 http://arxiv.org/abs/1511.07275
 """
-from __future__ import division
 from gym.envs.algorithmic import algorithmic_env
 
 
diff --git a/gym/envs/algorithmic/reversed_addition.py b/gym/envs/algorithmic/reversed_addition.py
index 976412d8b90..a14b6b52b73 100644
--- a/gym/envs/algorithmic/reversed_addition.py
+++ b/gym/envs/algorithmic/reversed_addition.py
@@ -1,4 +1,3 @@
-from __future__ import division
 from gym.envs.algorithmic import algorithmic_env
 
 
diff --git a/gym/envs/classic_control/rendering.py b/gym/envs/classic_control/rendering.py
index 84d0ca3167b..c80e6e453a4 100644
--- a/gym/envs/classic_control/rendering.py
+++ b/gym/envs/classic_control/rendering.py
@@ -1,9 +1,7 @@
 """
 2D rendering framework
 """
-from __future__ import division
 import os
-import six
 import sys
 
 if "Apple" in sys.version:
@@ -46,7 +44,7 @@ def get_display(spec):
     """
     if spec is None:
         return None
-    elif isinstance(spec, six.string_types):
+    elif isinstance(spec, str):
         return pyglet.canvas.Display(spec)
     else:
         raise error.Error('Invalid display specification: {}. (Must be a string like :0 or None.)'.format(spec))
diff --git a/gym/envs/tests/test_envs.py b/gym/envs/tests/test_envs.py
index d1c0ad0a71f..8c6abd7fb63 100644
--- a/gym/envs/tests/test_envs.py
+++ b/gym/envs/tests/test_envs.py
@@ -51,7 +51,6 @@ def test_random_rollout():
 
 
 def test_env_render_result_is_immutable():
-    from six import string_types
     environs = [
         envs.make('Taxi-v3'),
         envs.make('FrozenLake-v0'),
@@ -61,5 +60,5 @@ def test_env_render_result_is_immutable():
     for env in environs:
         env.reset()
         output = env.render(mode='ansi')
-        assert isinstance(output, string_types)
+        assert isinstance(output, str)
         env.close()
diff --git a/gym/envs/tests/test_envs_semantics.py b/gym/envs/tests/test_envs_semantics.py
index 4843375f677..4ebb6f14bb9 100644
--- a/gym/envs/tests/test_envs_semantics.py
+++ b/gym/envs/tests/test_envs_semantics.py
@@ -4,7 +4,6 @@
 """
 
 
-from __future__ import unicode_literals
 import json
 import hashlib
 import os
diff --git a/gym/envs/toy_text/frozen_lake.py b/gym/envs/toy_text/frozen_lake.py
index a4ab92ea42a..36ec7d170c7 100644
--- a/gym/envs/toy_text/frozen_lake.py
+++ b/gym/envs/toy_text/frozen_lake.py
@@ -2,7 +2,7 @@
 from contextlib import closing
 
 import numpy as np
-from six import StringIO, b
+from io import StringIO
 
 from gym import utils
 from gym.envs.toy_text import discrete
diff --git a/gym/envs/toy_text/taxi.py b/gym/envs/toy_text/taxi.py
index abe361c6f20..9a7deadd3f6 100644
--- a/gym/envs/toy_text/taxi.py
+++ b/gym/envs/toy_text/taxi.py
@@ -1,6 +1,6 @@
 import sys
 from contextlib import closing
-from six import StringIO
+from io import StringIO
 from gym import utils
 from gym.envs.toy_text import discrete
 import numpy as np
diff --git a/gym/utils/colorize.py b/gym/utils/colorize.py
index da70184991a..0e7fe054c84 100644
--- a/gym/utils/colorize.py
+++ b/gym/utils/colorize.py
@@ -21,15 +21,10 @@ def colorize(string, color, bold=False, highlight = False):
     blue, magenta, cyan, white, crimson
     """
 
-    # Import six here so that `utils` has no import-time dependencies.
-    # We want this since we use `utils` during our import-time sanity checks
-    # that verify that our dependencies (including six) are actually present.
-    import six
-
     attr = []
     num = color2num[color]
     if highlight: num += 10
-    attr.append(six.u(str(num)))
-    if bold: attr.append(six.u('1'))
-    attrs = six.u(';').join(attr)
-    return six.u('\x1b[%sm%s\x1b[0m') % (attrs, string)
+    attr.append(str(num))
+    if bold: attr.append('1')
+    attrs = ';'.join(attr)
+    return '\x1b[%sm%s\x1b[0m' % (attrs, string)
diff --git a/gym/utils/seeding.py b/gym/utils/seeding.py
index 39fe3422717..dfd7076c213 100644
--- a/gym/utils/seeding.py
+++ b/gym/utils/seeding.py
@@ -2,14 +2,13 @@
 import numpy as np
 import os
 import random as _random
-from six import integer_types
 import struct
 import sys
 
 from gym import error
 
 def np_random(seed=None):
-    if seed is not None and not (isinstance(seed, integer_types) and 0 <= seed):
+    if seed is not None and not (isinstance(seed, int) and 0 <= seed):
         raise error.Error('Seed must be a non-negative integer or omitted, not {}'.format(seed))
 
     seed = create_seed(seed)
@@ -58,7 +57,7 @@ def create_seed(a=None, max_bytes=8):
         a = a.encode('utf8')
         a += hashlib.sha512(a).digest()
         a = _bigint_from_bytes(a[:max_bytes])
-    elif isinstance(a, integer_types):
+    elif isinstance(a, int):
         a = a % 2**(8 * max_bytes)
     else:
         raise error.Error('Invalid type for seed: {} ({})'.format(type(a), a))
diff --git a/gym/wrappers/monitor.py b/gym/wrappers/monitor.py
index e26f82bea18..b2b6733607a 100644
--- a/gym/wrappers/monitor.py
+++ b/gym/wrappers/monitor.py
@@ -1,7 +1,7 @@
 import gym
 from gym import Wrapper
 from gym import error, version, logger
-import os, json, numpy as np, six
+import os, json, numpy as np
 from gym.wrappers.monitoring import stats_recorder, video_recorder
 from gym.utils import atomic_write, closer
 from gym.utils.json_utils import json_encode_np
@@ -66,10 +66,7 @@ def _start(self, directory, video_callable=None, force=False, resume=False,
 
         if not os.path.exists(directory):
             logger.info('Creating monitor directory %s', directory)
-            if six.PY3:
-                os.makedirs(directory, exist_ok=True)
-            else:
-                os.makedirs(directory)
+            os.makedirs(directory, exist_ok=True)
 
         if video_callable is None:
             video_callable = capped_cubic_video_schedule
diff --git a/gym/wrappers/monitoring/video_recorder.py b/gym/wrappers/monitoring/video_recorder.py
index 7af82bf026f..fb14c709094 100644
--- a/gym/wrappers/monitoring/video_recorder.py
+++ b/gym/wrappers/monitoring/video_recorder.py
@@ -5,8 +5,7 @@
 import os.path
 import distutils.spawn, distutils.version
 import numpy as np
-from six import StringIO
-import six
+from io import StringIO
 from gym import error, logger
 
 def touch(path):
@@ -182,9 +181,8 @@ def __init__(self, output_path, frames_per_sec):
         self.frames = []
 
     def capture_frame(self, frame):
-        from six import string_types
         string = None
-        if isinstance(frame, string_types):
+        if isinstance(frame, str):
             string = frame
         elif isinstance(frame, StringIO):
             string = frame.getvalue()
@@ -193,10 +191,10 @@ def capture_frame(self, frame):
 
         frame_bytes = string.encode('utf-8')
 
-        if frame_bytes[-1:] != six.b('\n'):
+        if frame_bytes[-1:] != b'\n':
             raise error.InvalidFrame('Frame must end with a newline: """{}"""'.format(string))
 
-        if six.b('\r') in frame_bytes:
+        if b'\r' in frame_bytes:
             raise error.InvalidFrame('Frame contains carriage returns (only newlines are allowed: """{}"""'.format(string))
 
         self.frames.append(frame_bytes)
@@ -208,14 +206,14 @@ def close(self):
         # Turn frames into events: clear screen beforehand
         # https://rosettacode.org/wiki/Terminal_control/Clear_the_screen#Python
         # https://rosettacode.org/wiki/Terminal_control/Cursor_positioning#Python
-        clear_code = six.b("%c[2J\033[1;1H" % (27))
+        clear_code = b"%c[2J\033[1;1H" % (27)
         # Decode the bytes as UTF-8 since JSON may only contain UTF-8
-        events = [ (frame_duration, (clear_code+frame.replace(six.b('\n'),six.b('\r\n'))).decode('utf-8'))  for frame in self.frames ]
+        events = [ (frame_duration, (clear_code+frame.replace(b'\n', b'\r\n')).decode('utf-8'))  for frame in self.frames ]
 
         # Calculate frame size from the largest frames.
         # Add some padding since we'll get cut off otherwise.
-        height = max([frame.count(six.b('\n')) for frame in self.frames]) + 1
-        width = max([max([len(line) for line in frame.split(six.b('\n'))]) for frame in self.frames]) + 2
+        height = max([frame.count(b'\n') for frame in self.frames]) + 1
+        width = max([max([len(line) for line in frame.split(b'\n')]) for frame in self.frames]) + 2
 
         data = {
             "version": 1,
diff --git a/scripts/generate_json.py b/scripts/generate_json.py
index 3cc938ccb89..49bc9e19432 100644
--- a/scripts/generate_json.py
+++ b/scripts/generate_json.py
@@ -1,4 +1,3 @@
-from __future__ import unicode_literals
 from gym import envs, spaces, logger
 import json
 import os
diff --git a/setup.py b/setup.py
index 9f50f5e4033..0feeb85e7fa 100644
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,7 @@
                 if package.startswith('gym')],
       zip_safe=False,
       install_requires=[
-          'scipy', 'numpy>=1.10.4', 'six', 'pyglet>=1.4.0,<=1.5.0', 'cloudpickle>=1.2.0,<1.4.0',
+          'scipy', 'numpy>=1.10.4', 'pyglet>=1.4.0,<=1.5.0', 'cloudpickle>=1.2.0,<1.4.0',
           'enum34~=1.1.6;python_version<"3.4"',
       ],
       extras_require=extras,

fixes https://github.com/openai/gym/issues/1823