diff --git a/python/ovs/db/data.py b/python/ovs/db/data.py
index 9cbf425..c2915e1 100644
--- a/python/ovs/db/data.py
+++ b/python/ovs/db/data.py
@@ -117,7 +117,7 @@ class Atom(object):
                 and isinstance(json, real_types))
             or (type_ == ovs.db.types.BooleanType and isinstance(json, bool))
             or (type_ == ovs.db.types.StringType
-                and isinstance(json, (str, unicode)))):
+                and isinstance(json, six.string_types))):
             atom = Atom(type_, json)
         elif type_ == ovs.db.types.UuidType:
             atom = Atom(type_, ovs.ovsuuid.from_json(json, symtab))
@@ -129,7 +129,7 @@ class Atom(object):
     @staticmethod
     def from_python(base, value):
         value = ovs.db.parser.float_to_int(value)
-        if type(value) in base.type.python_types:
+        if isinstance(value, base.type.python_types):
             atom = Atom(base.type, value)
         else:
             raise error.Error("expected %s, got %s" % (base.type, type(value)))
@@ -247,7 +247,7 @@ class Atom(object):
             t = ovs.db.types.RealType
         elif isinstance(x, bool):
             t = ovs.db.types.BooleanType
-        elif isinstance(x, (str, unicode)):
+        elif isinstance(x, six.string_types):
             t = ovs.db.types.StringType
         elif isinstance(x, uuid):
             t = ovs.db.types.UuidType
diff --git a/python/ovs/db/parser.py b/python/ovs/db/parser.py
index 293dd98..d48a790 100644
--- a/python/ovs/db/parser.py
+++ b/python/ovs/db/parser.py
@@ -33,7 +33,10 @@ class Parser(object):
             member = float_to_int(self.json[name])
             if is_identifier(member) and "id" in types:
                 return member
-            if len(types) and type(member) not in types:
+            try:
+                if len(types) and not isinstance(member, tuple(types)):
+                   self.__raise_error("Type mismatch for member '%s'." % name)
+            except TypeError:
                 self.__raise_error("Type mismatch for member '%s'." % name)
             return member
         else:
@@ -78,7 +81,7 @@ id_re = re.compile("[_a-zA-Z][_a-zA-Z0-9]*$")
 
 
 def is_identifier(s):
-    return type(s) in [str, unicode] and id_re.match(s)
+    return isinstance(s, six.string_types) and id_re.match(s)
 
 
 def json_type_to_string(type_):
@@ -95,15 +98,16 @@ def json_type_to_string(type_):
         return "array"
     elif issubclass(type_, number_types):
         return "number"
-    elif issubclass(type_, (str, unicode)):
+    elif issubclass(type_, six.string_types):
         return "string"
     else:
         return "<invalid>"
 
 
 def unwrap_json(json, name, types, desc):
-    if (type(json) not in (list, tuple) or len(json) != 2 or json[0] != name or
-        type(json[1]) not in types):
+    if (not isinstance(json, (list, tuple))
+            or len(json) != 2 or json[0] != name
+            or not isinstance(json[1], tuple(types))):
         raise error.Error('expected ["%s", <%s>]' % (name, desc), json)
     return json[1]
 
diff --git a/python/ovs/db/schema.py b/python/ovs/db/schema.py
index 399129e..1c492f8 100644
--- a/python/ovs/db/schema.py
+++ b/python/ovs/db/schema.py
@@ -67,8 +67,8 @@ class DbSchema(object):
     def from_json(json):
         parser = ovs.db.parser.Parser(json, "database schema")
         name = parser.get("name", ['id'])
-        version = parser.get_optional("version", [str, unicode])
-        parser.get_optional("cksum", [str, unicode])
+        version = parser.get_optional("version", six.string_types)
+        parser.get_optional("cksum", six.string_types)
         tablesJson = parser.get("tables", [dict])
         parser.finish()
 
@@ -133,8 +133,8 @@ class IdlSchema(DbSchema):
     @staticmethod
     def from_json(json):
         parser = ovs.db.parser.Parser(json, "IDL schema")
-        idlPrefix = parser.get("idlPrefix", [str, unicode])
-        idlHeader = parser.get("idlHeader", [str, unicode])
+        idlPrefix = parser.get("idlPrefix", six.string_types)
+        idlHeader = parser.get("idlHeader", six.string_types)
 
         subjson = dict(json)
         del subjson["idlPrefix"]
@@ -152,7 +152,7 @@ def column_set_from_json(json, columns):
         raise error.Error("array of distinct column names expected", json)
     else:
         for column_name in json:
-            if type(column_name) not in [str, unicode]:
+            if not isinstance(column_name, six.string_types):
                 raise error.Error("array of distinct column names expected",
                                   json)
             elif column_name not in columns:
@@ -260,8 +260,9 @@ class ColumnSchema(object):
         parser = ovs.db.parser.Parser(json, "schema for column %s" % name)
         mutable = parser.get_optional("mutable", [bool], True)
         ephemeral = parser.get_optional("ephemeral", [bool], False)
-        type_ = ovs.db.types.Type.from_json(parser.get("type",
-                                                       [dict, str, unicode]))
+        _types = list(six.string_types)
+        _types.extend([dict])
+        type_ = ovs.db.types.Type.from_json(parser.get("type", _types))
         parser.finish()
 
         return ColumnSchema(name, mutable, not ephemeral, type_)
diff --git a/python/ovs/db/types.py b/python/ovs/db/types.py
index d7ce00a..f4d1f90 100644
--- a/python/ovs/db/types.py
+++ b/python/ovs/db/types.py
@@ -39,7 +39,7 @@ class AtomicType(object):
 
     @staticmethod
     def from_json(json):
-        if type(json) not in [str, unicode]:
+        if not isinstance(json, six.string_types):
             raise error.Error("atomic-type expected", json)
         else:
             return AtomicType.from_string(json)
@@ -64,7 +64,7 @@ VoidType = AtomicType("void", None, ())
 IntegerType = AtomicType("integer", 0, six.integer_types)
 RealType = AtomicType("real", 0.0, REAL_PYTHON_TYPES)
 BooleanType = AtomicType("boolean", False, (bool,))
-StringType = AtomicType("string", "", (str, unicode))
+StringType = AtomicType("string", "", six.string_types)
 UuidType = AtomicType("uuid", ovs.ovsuuid.zero(), (uuid.UUID,))
 
 ATOMIC_TYPES = [VoidType, IntegerType, RealType, BooleanType, StringType,
@@ -166,11 +166,12 @@ class BaseType(object):
 
     @staticmethod
     def from_json(json):
-        if type(json) in [str, unicode]:
+        if isinstance(json, six.string_types):
             return BaseType(AtomicType.from_json(json))
 
         parser = ovs.db.parser.Parser(json, "ovsdb type")
-        atomic_type = AtomicType.from_json(parser.get("type", [str, unicode]))
+        atomic_type = AtomicType.from_json(parser.get("type",
+                                                      six.string_types))
 
         base = BaseType(atomic_type)
 
@@ -199,7 +200,8 @@ class BaseType(object):
         elif base.type == UuidType:
             base.ref_table_name = parser.get_optional("refTable", ['id'])
             if base.ref_table_name:
-                base.ref_type = parser.get_optional("refType", [str, unicode],
+                base.ref_type = parser.get_optional("refType",
+                                                    six.string_types,
                                                    "strong")
                 if base.ref_type not in ['strong', 'weak']:
                     raise error.Error('refType must be "strong" or "weak" '
@@ -487,14 +489,18 @@ class Type(object):
 
     @staticmethod
     def from_json(json):
-        if type(json) in [str, unicode]:
+        if isinstance(json, six.string_types):
             return Type(BaseType.from_json(json))
 
         parser = ovs.db.parser.Parser(json, "ovsdb type")
-        key_json = parser.get("key", [dict, str, unicode])
-        value_json = parser.get_optional("value", [dict, str, unicode])
+        _types = list(six.string_types)
+        _types.extend([dict])
+        key_json = parser.get("key", _types)
+        value_json = parser.get_optional("value", _types)
         min_json = parser.get_optional("min", [int])
-        max_json = parser.get_optional("max", [int, str, unicode])
+        _types = list(six.string_types)
+        _types.extend([int])
+        max_json = parser.get_optional("max", _types)
         parser.finish()
 
         key = BaseType.from_json(key_json)
diff --git a/python/ovs/json.py b/python/ovs/json.py
index 042f366..c1dcd63 100644
--- a/python/ovs/json.py
+++ b/python/ovs/json.py
@@ -61,10 +61,13 @@ class _Serializer(object):
             self.stream.write(u"%d" % obj)
         elif isinstance(obj, float):
             self.stream.write("%.15g" % obj)
-        elif isinstance(obj, unicode):
+        elif isinstance(obj, six.text_type):
+            # unicode() on Python 2, or str() in Python 3 (always unicode)
             self.__serialize_string(obj)
         elif isinstance(obj, str):
-            self.__serialize_string(unicode(obj))
+            # This is for Python 2, where this comes out to unicode(str()).
+            # For Python 3, it's str(str()), but it's harmless.
+            self.__serialize_string(six.text_type(obj))
         elif isinstance(obj, dict):
             self.stream.write(u"{")
 
@@ -79,7 +82,7 @@ class _Serializer(object):
                 if i > 0:
                     self.stream.write(u",")
                     self.__indent_line()
-                self.__serialize_string(unicode(key))
+                self.__serialize_string(six.text_type(key))
                 self.stream.write(u":")
                 if self.pretty:
                     self.stream.write(u' ')
@@ -144,12 +147,16 @@ def from_file(name):
 
 
 def from_string(s):
-    try:
-        s = unicode(s, 'utf-8')
-    except UnicodeDecodeError as e:
-        seq = ' '.join(["0x%2x" % ord(c)
-                        for c in e.object[e.start:e.end] if ord(c) >= 0x80])
-        return ("not a valid UTF-8 string: invalid UTF-8 sequence %s" % seq)
+    if not isinstance(s, six.text_type):
+        # We assume the input is a string.  We will only hit this case for a
+        # str in Python 2 which is not unicode, so we need to go ahead and
+        # decode it.
+        try:
+            s = six.text_type(s, 'utf-8')
+        except UnicodeDecodeError as e:
+            seq = ' '.join(["0x%2x" % ord(c)
+                           for c in e.object[e.start:e.end] if ord(c) >= 0x80])
+            return "not a valid UTF-8 string: invalid UTF-8 sequence %s" % seq
     p = Parser(check_trailer=True)
     p.feed(s)
     return p.finish()
diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py
index 99aa27c..f576b25 100644
--- a/python/ovs/jsonrpc.py
+++ b/python/ovs/jsonrpc.py
@@ -15,6 +15,8 @@
 import errno
 import os
 
+import six
+
 import ovs.json
 import ovs.poller
 import ovs.reconnect
@@ -115,7 +117,7 @@ class Message(object):
 
         if "method" in json:
             method = json.pop("method")
-            if type(method) not in [str, unicode]:
+            if not isinstance(method, six.string_types):
                 return "method is not a JSON string"
         else:
             method = None
@@ -318,7 +320,7 @@ class Connection(object):
     def __process_msg(self):
         json = self.parser.finish()
         self.parser = None
-        if type(json) in [str, unicode]:
+        if isinstance(json, six.string_types):
             # XXX rate-limit
             vlog.warn("%s: error parsing stream: %s" % (self.name, json))
             self.error(errno.EPROTO)
diff --git a/python/ovs/ovsuuid.py b/python/ovs/ovsuuid.py
index f2d48ea..a8f0d14 100644
--- a/python/ovs/ovsuuid.py
+++ b/python/ovs/ovsuuid.py
@@ -15,6 +15,7 @@
 import re
 import uuid
 
+import six
 from six.moves import range
 
 from ovs.db import error
@@ -40,7 +41,7 @@ def from_string(s):
 
 def from_json(json, symtab=None):
     try:
-        s = ovs.db.parser.unwrap_json(json, "uuid", [str, unicode], "string")
+        s = ovs.db.parser.unwrap_json(json, "uuid", six.string_types, "string")
         if not uuidRE.match(s):
             raise error.Error("\"%s\" is not a valid UUID" % s, json)
         return uuid.UUID(s)
@@ -49,7 +50,7 @@ def from_json(json, symtab=None):
             raise e
         try:
             name = ovs.db.parser.unwrap_json(json, "named-uuid",
-                                             [str, unicode], "string")
+                                             six.string_types, "string")
         except error.Error:
             raise e
 
diff --git a/python/ovs/unixctl/server.py b/python/ovs/unixctl/server.py
index 9744cf2..4ea19a1 100644
--- a/python/ovs/unixctl/server.py
+++ b/python/ovs/unixctl/server.py
@@ -17,6 +17,7 @@ import errno
 import os
 import types
 
+import six
 from six.moves import range
 
 import ovs.dirs
@@ -125,7 +126,7 @@ class UnixctlConnection(object):
                     break
 
             if error is None:
-                unicode_params = [unicode(p) for p in params]
+                unicode_params = [six.text_type(p) for p in params]
                 command.callback(self, unicode_params, command.aux)
 
         if error:
