diff --git a/aksetup_helper.py b/aksetup_helper.py
index 12d888c984c1f931aa26353cab0e9b68ce4bb3a0..c527684ffff87a9c16855fe24f1f4937fa537866 100644
--- a/aksetup_helper.py
+++ b/aksetup_helper.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 import setuptools  # noqa
 from setuptools import Extension
 
@@ -278,11 +280,11 @@ class ConfigSchema:
         if "__builtins__" in filevars:
             del filevars["__builtins__"]
 
-        for key, value in config.items():
+        for key, value in list(config.items()):
             if value is not None:
                 filevars[key] = value
 
-        keys = filevars.keys()
+        keys = list(filevars.keys())
         keys.sort()
 
         outf = open(filename, "w")
diff --git a/configure.py b/configure.py
index afe32be6ede21b4c009042ac27a5e9dd57a27cb6..282bc2b21c4100d6a10d4a84a2410fd7bb185eeb 100755
--- a/configure.py
+++ b/configure.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 #! /usr/bin/env python
 
 from aksetup_helper import configure_frontend
diff --git a/contrib/fortran-to-opencl/translate.py b/contrib/fortran-to-opencl/translate.py
index 4c3486f4d52c135aacd2a915c90089fd71e8acb2..66f6e1dbfa80c2647313177730153ee75e80f4d0 100644
--- a/contrib/fortran-to-opencl/translate.py
+++ b/contrib/fortran-to-opencl/translate.py
@@ -1,4 +1,8 @@
 from __future__ import division, with_statement
+from __future__ import absolute_import
+from __future__ import print_function
+import six
+from six.moves import range
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
@@ -170,11 +174,11 @@ class FortranExpressionParser(ExpressionParserBase):
             if value.startswith("."):
                 prev_value = value
                 value = "0"+value
-                print value, prev_value
+                print(value, prev_value)
             elif value.startswith("-."):
                 prev_value = value
                 value = "-0"+value[1:]
-                print value, prev_value
+                print(value, prev_value)
             return TypedLiteral(value, dtype)
 
         elif next_tag is _identifier:
@@ -604,8 +608,8 @@ class Scope(object):
 
     def known_names(self):
         return (self.used_names
-                | set(self.dim_map.iterkeys())
-                | set(self.type_map.iterkeys()))
+                | set(six.iterkeys(self.dim_map))
+                | set(six.iterkeys(self.type_map)))
 
     def is_known(self, name):
         return (name in self.used_names
@@ -1314,7 +1318,7 @@ class F2CLTranslator(FTreeWalkerBase):
                         % node.loopcontrol)
 
             if not isinstance(step, int):
-                print type(step)
+                print(type(step))
                 raise TranslationError(
                         "non-constant steps not yet supported: %s" % step)
 
diff --git a/doc/conf.py b/doc/conf.py
index eb9ba09b61a209216fa9c6d3c09c083199fc9937..090f716602d85c9ee3d34a4de90ab6a12e99dc77 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 # -*- coding: utf-8 -*-
 #
 # PyOpenCL documentation build configuration file, created by
@@ -49,7 +50,7 @@ copyright = '2009, Andreas Kloeckner'
 #
 # The short X.Y version.
 ver_dic = {}
-execfile("../pyopencl/version.py", ver_dic)
+exec(compile(open("../pyopencl/version.py").read(), "../pyopencl/version.py", 'exec'), ver_dic)
 version = ".".join(str(x) for x in ver_dic["VERSION"])
 # The full version, including alpha/beta/rc tags.
 release = ver_dic["VERSION_TEXT"]
diff --git a/doc/make_constants.py b/doc/make_constants.py
index 6416ca0f73f9041514cd3fe554b0a8a483d6b29d..2d24960cdaff4915fbda437dc26f6a8651a5d68b 100644
--- a/doc/make_constants.py
+++ b/doc/make_constants.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
 __license__ = """
@@ -331,42 +333,42 @@ cls_ext_lookup = {
 
 
 def doc_class(cls):
-    print ".. class :: %s" % cls.__name__
-    print
+    print(".. class :: %s" % cls.__name__)
+    print()
     if cls.__name__.startswith("gl_"):
-        print "    Only available when PyOpenCL is compiled with GL support."
-        print "    See :func:`have_gl`."
-        print
+        print("    Only available when PyOpenCL is compiled with GL support.")
+        print("    See :func:`have_gl`.")
+        print()
 
     if cls in cls_ext_lookup:
         for l in get_extra_lines(cls_ext_lookup[cls]):
-            print l
+            print(l)
 
     cls_const_ext = const_ext_lookup.get(cls, {})
     for name in sorted(dir(cls)):
         if not name.startswith("_") and not name in ["to_string", "names", "values"]:
-            print "    .. attribute :: %s" % name
+            print("    .. attribute :: %s" % name)
 
             if name in cls_const_ext:
                 for l in get_extra_lines(cls_const_ext[name]):
-                    print "    "+l
+                    print("    "+l)
 
-    print "    .. method :: to_string(value)"
-    print
-    print "        Returns a :class:`str` representing *value*."
-    print
-    print "        .. versionadded:: 0.91"
-    print
+    print("    .. method :: to_string(value)")
+    print()
+    print("        Returns a :class:`str` representing *value*.")
+    print()
+    print("        .. versionadded:: 0.91")
+    print()
 
 
 if not cl.have_gl():
-    print ".. warning::"
-    print
-    print "    This set of PyOpenCL documentation is incomplete because it"
-    print "    was generated on a PyOpenCL build that did not support OpenGL."
-    print
-
-print ".. This is an automatically generated file. DO NOT EDIT"
-print
+    print(".. warning::")
+    print()
+    print("    This set of PyOpenCL documentation is incomplete because it")
+    print("    was generated on a PyOpenCL build that did not support OpenGL.")
+    print()
+
+print(".. This is an automatically generated file. DO NOT EDIT")
+print()
 for cls in cl.CONSTANT_CLASSES:
     doc_class(cls)
diff --git a/examples/benchmark.py b/examples/benchmark.py
index d04f183304edef9fb4965a5e70aa1b1cb38a8b69..3251a55ca3d0338edefd11c1d507f2d5b77272c0 100644
--- a/examples/benchmark.py
+++ b/examples/benchmark.py
@@ -1,6 +1,7 @@
 # example provided by Roger Pau Monn'e
 
 from __future__ import print_function
+from __future__ import absolute_import
 import pyopencl as cl
 import numpy
 import numpy.linalg as la
diff --git a/examples/demo-struct-reduce.py b/examples/demo-struct-reduce.py
index c0c26e34743687a281c534c05d9c8cb74c6587ec..2b0d9803f1fdd32e85a2da7fe245297a8ac5cf95 100644
--- a/examples/demo-struct-reduce.py
+++ b/examples/demo-struct-reduce.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 import numpy as np
 import pyopencl as cl
 
diff --git a/examples/demo.py b/examples/demo.py
index 1b694a88062aa101ca80c72df5676ede9c474f1c..8fcdd5b4291dcd8c848a15885e39d718f99bc222 100644
--- a/examples/demo.py
+++ b/examples/demo.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
diff --git a/examples/demo_array.py b/examples/demo_array.py
index 41b0f79ef2ccb74a807a8da5aff5eedf6a3bb15f..c645b372632b8792d302658bbfa6c263b051491e 100644
--- a/examples/demo_array.py
+++ b/examples/demo_array.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 import pyopencl as cl
 import pyopencl.array as cl_array
 import numpy
diff --git a/examples/demo_elementwise.py b/examples/demo_elementwise.py
index 21646c4f42a8cce495c02aef7beae5d4a2ceaffe..a8a3a007c094cf9b1ca7d3fc66142b7817a8b83d 100644
--- a/examples/demo_elementwise.py
+++ b/examples/demo_elementwise.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
diff --git a/examples/demo_elementwise_complex.py b/examples/demo_elementwise_complex.py
index 7845530b13c152db9e35479ba7ea3bcbcd56064d..9e04e2dd5a4f09c4235e860de1aa32dfc41a714f 100644
--- a/examples/demo_elementwise_complex.py
+++ b/examples/demo_elementwise_complex.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 import pyopencl as cl
 import pyopencl.array as cl_array
 import numpy
@@ -48,7 +50,7 @@ complex_prod(5, a_gpu, b_gpu, c_gpu)
 
 c_gpu_real = cl_array.empty(queue, len(a_gpu), dtype=numpy.float32)
 real_part(c_gpu, c_gpu_real)
-print c_gpu.get().real - c_gpu_real.get()
+print(c_gpu.get().real - c_gpu_real.get())
 
-print la.norm(c_gpu.get() - (5*a_gpu.get()*b_gpu.get()))
+print(la.norm(c_gpu.get() - (5*a_gpu.get()*b_gpu.get())))
 assert la.norm(c_gpu.get() - (5*a_gpu.get()*b_gpu.get())) < 1e-5
diff --git a/examples/demo_mandelbrot.py b/examples/demo_mandelbrot.py
index e63fec56f07306306699ea8aedde3a7034c54ac2..802dfb215802c70e86bdc7534d401b4efe2f173b 100644
--- a/examples/demo_mandelbrot.py
+++ b/examples/demo_mandelbrot.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 # I found this example for PyCuda here:
 # http://wiki.tiker.net/PyCuda/Examples/Mandelbrot
 #
@@ -22,6 +24,7 @@ import time
 import numpy as np
 
 import pyopencl as cl
+from six.moves import range
 
 # You can choose a calculation routine below (calc_fractal), uncomment
 # one of the three lines to test the three variations
@@ -108,7 +111,7 @@ calc_fractal = calc_fractal_opencl
 
 if __name__ == '__main__':
     try:
-        import Tkinter as tk
+        import six.moves.tkinter as tk
     except ImportError:
         # Python 3
         import tkinter as tk
diff --git a/examples/demo_meta_codepy.py b/examples/demo_meta_codepy.py
index c080109b9dcfe45c16525db2eaa7709f9250b3a9..7ab9958f490bb17b5a55b18c2e9649909ac8c703 100644
--- a/examples/demo_meta_codepy.py
+++ b/examples/demo_meta_codepy.py
@@ -1,6 +1,8 @@
+from __future__ import absolute_import
 import pyopencl as cl
 import numpy
 import numpy.linalg as la
+from six.moves import range
 
 local_size = 256
 thread_strides = 32
diff --git a/examples/demo_meta_template.py b/examples/demo_meta_template.py
index fc64934385b58c7ac6a2d5b72a5b4fb1327de688..76b5f65bf88ba938273b640831a998f93cd94812 100644
--- a/examples/demo_meta_template.py
+++ b/examples/demo_meta_template.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 import pyopencl as cl
 import numpy
 import numpy.linalg as la
diff --git a/examples/download-examples-from-wiki.py b/examples/download-examples-from-wiki.py
index 8740391051b722a81c42900c3a74f09cb047158b..459d797f13d895b3e4a90e0a8b145a1f6fd698b4 100755
--- a/examples/download-examples-from-wiki.py
+++ b/examples/download-examples-from-wiki.py
@@ -1,7 +1,9 @@
+from __future__ import absolute_import
+from __future__ import print_function
 #! /usr/bin/env python
 
-import xmlrpclib
-destwiki = xmlrpclib.ServerProxy("http://wiki.tiker.net?action=xmlrpc2")
+import six.moves.xmlrpc_client
+destwiki = six.moves.xmlrpc_client.ServerProxy("http://wiki.tiker.net?action=xmlrpc2")
 
 import os
 try:
@@ -9,8 +11,8 @@ try:
 except OSError:
     pass
 
-print "downloading  wiki examples to wiki-examples/..."
-print "fetching page list..."
+print("downloading  wiki examples to wiki-examples/...")
+print("fetching page list...")
 all_pages = destwiki.getAllPages()
 
 
@@ -20,7 +22,7 @@ for page in all_pages:
     if not page.startswith("PyOpenCL/Examples/"):
         continue
 
-    print page
+    print(page)
     try:
         content = destwiki.getPage(page)
 
@@ -33,7 +35,7 @@ for page in all_pages:
 
         outfname = os.path.join("wiki-examples", fname+".py")
         if exists(outfname):
-            print "%s exists, refusing to overwrite." % outfname
+            print("%s exists, refusing to overwrite." % outfname)
         else:
             outf = open(outfname, "w")
             outf.write(code)
@@ -44,13 +46,13 @@ for page in all_pages:
 
             outfname = os.path.join("wiki-examples", att_name)
             if exists(outfname):
-                print "%s exists, refusing to overwrite." % outfname
+                print("%s exists, refusing to overwrite." % outfname)
             else:
                 outf = open(outfname, "w")
                 outf.write(str(content))
                 outf.close()
 
-    except Exception, e:
-        print "Error when processing %s: %s" % (page, e)
+    except Exception as e:
+        print("Error when processing %s: %s" % (page, e))
         from traceback import print_exc
         print_exc()
diff --git a/examples/dump-performance.py b/examples/dump-performance.py
index 97fa0544aaf357f0769a5ff6d9aa623c26dda4ef..42946a791d7ef876885e7efcabb830b1d906e567 100644
--- a/examples/dump-performance.py
+++ b/examples/dump-performance.py
@@ -1,6 +1,9 @@
 from __future__ import division
+from __future__ import absolute_import
+from __future__ import print_function
 import pyopencl as cl
 import pyopencl.characterize.performance as perf
+from six.moves import range
 
 
 
@@ -9,27 +12,27 @@ def main():
     ctx = cl.create_some_context()
 
     prof_overhead, latency = perf.get_profiling_overhead(ctx)
-    print "command latency: %g s" % latency
-    print "profiling overhead: %g s -> %.1f %%" % (
-            prof_overhead, 100*prof_overhead/latency)
+    print("command latency: %g s" % latency)
+    print("profiling overhead: %g s -> %.1f %%" % (
+            prof_overhead, 100*prof_overhead/latency))
     queue = cl.CommandQueue(ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
 
-    print "empty kernel: %g s" % perf.get_empty_kernel_time(queue)
-    print "float32 add: %g GOps/s" % (perf.get_add_rate(queue)/1e9)
+    print("empty kernel: %g s" % perf.get_empty_kernel_time(queue))
+    print("float32 add: %g GOps/s" % (perf.get_add_rate(queue)/1e9))
 
     for tx_type in [
             perf.HostToDeviceTransfer,
             perf.DeviceToHostTransfer,
             perf.DeviceToDeviceTransfer]:
-        print "----------------------------------------"
-        print tx_type.__name__
-        print "----------------------------------------"
+        print("----------------------------------------")
+        print(tx_type.__name__)
+        print("----------------------------------------")
 
-        print "latency: %g s" % perf.transfer_latency(queue, tx_type)
+        print("latency: %g s" % perf.transfer_latency(queue, tx_type))
         for i in range(6, 28, 2):
             bs = 1<<i
-            print "bandwidth @ %d bytes: %g GB/s" % (
-                    bs, perf.transfer_bandwidth(queue, tx_type, bs)/1e9)
+            print("bandwidth @ %d bytes: %g GB/s" % (
+                    bs, perf.transfer_bandwidth(queue, tx_type, bs)/1e9))
 
 
 
diff --git a/examples/dump-properties.py b/examples/dump-properties.py
index 7890c941c1ca5e48da020368dd21cba1aede470b..7d8a459efa1cf4af7ce4d9873a0eeb0ee71ff24f 100644
--- a/examples/dump-properties.py
+++ b/examples/dump-properties.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 import pyopencl as cl
 from optparse import OptionParser
 
@@ -76,8 +78,8 @@ for platform in cl.get_platforms():
                                     str_chd_type(iform.channel_data_type))
                                 for iform in formats)
 
-                    print "%s %s FORMATS: %s\n" % (
+                    print("%s %s FORMATS: %s\n" % (
                             cl.mem_object_type.to_string(itype),
                             cl.mem_flags.to_string(mf),
-                            formats)
+                            formats))
             del ctx
diff --git a/examples/gl_interop_demo.py b/examples/gl_interop_demo.py
index 99524cb30b3662b09aa4599d14d6df259ff6f340..da5ba3b0d6c84216a4a2273134c7cacef3a26b1f 100644
--- a/examples/gl_interop_demo.py
+++ b/examples/gl_interop_demo.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 from OpenGL.GL import *
 from OpenGL.GLUT import *
 from OpenGL.raw.GL.VERSION.GL_1_5 import glBufferData as rawGlBufferData
diff --git a/examples/gl_particle_animation.py b/examples/gl_particle_animation.py
index 6cd008b072089fe73efc425ea9074fb4cd67bd83..fc718081b117f494a76ec97ae1fab4b835cbbbac 100644
--- a/examples/gl_particle_animation.py
+++ b/examples/gl_particle_animation.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 # Visualization of particles with gravity
 # Source: http://enja.org/2010/08/27/adventures-in-opencl-part-2-particles-with-opengl/
 
diff --git a/examples/narray.py b/examples/narray.py
index 40ba945042b8d6337d7d4139deb1991d20532d81..78b9bb9205b326b207730d411524fad93fd2c142 100644
--- a/examples/narray.py
+++ b/examples/narray.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 # example by Roger Pau Monn'e
 import pyopencl as cl
 import numpy as np
diff --git a/examples/transpose.py b/examples/transpose.py
index b6a073deab6ca5a4f219e5c19640e175dd8cb8cd..99f68a28e4bc97e889248e01e7d145172587cf3f 100644
--- a/examples/transpose.py
+++ b/examples/transpose.py
@@ -2,9 +2,12 @@
 # originally for PyCUDA by Hendrik Riedmann <riedmann@dam.brown.edu>
 
 from __future__ import division
+from __future__ import absolute_import
+from __future__ import print_function
 import pyopencl as cl
 import numpy
 import numpy.linalg as la
+from six.moves import range
 
 
 
diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index 84ffe1169689ebe577e6bc8e3d8e786c1a012481..816423a4e7fbab1ad739659f74c2f2ed79912900 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -1,6 +1,11 @@
 # -*- coding: utf-8 -*-
 
 from __future__ import division
+from __future__ import absolute_import
+from __future__ import print_function
+import six
+from six.moves import zip
+from six.moves import input
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
@@ -114,7 +119,7 @@ class Program(object):
             context, source = arg1, arg2
 
             import sys
-            if isinstance(source, unicode) and sys.version_info < (3,):
+            if isinstance(source, six.text_type) and sys.version_info < (3,):
                 from warnings import warn
                 warn("Received OpenCL source code in Unicode, "
                      "should be ASCII string. Attempting conversion.",
@@ -178,7 +183,7 @@ class Program(object):
     def build(self, options=[], devices=None, cache_dir=None):
         if isinstance(options, str):
             options = [options]
-        elif isinstance(options, unicode):
+        elif isinstance(options, six.text_type):
             options = [options.encode("utf8")]
 
         options = (options
@@ -219,7 +224,7 @@ class Program(object):
     def _build_and_catch_errors(self, build_func, options, source=None):
         try:
             return build_func()
-        except _cl.RuntimeError, e:
+        except _cl.RuntimeError as e:
             from pytools import Record
 
             class ErrorRecord(Record):
@@ -319,8 +324,8 @@ def _add_functionality():
 
         return property(result)
 
-    for cls, (info_method, info_class) in cls_to_info_cls.iteritems():
-        for info_name, info_value in info_class.__dict__.iteritems():
+    for cls, (info_method, info_class) in six.iteritems(cls_to_info_cls):
+        for info_name, info_value in six.iteritems(info_class.__dict__):
             if info_name == "to_string" or info_name.startswith("_"):
                 continue
 
@@ -419,7 +424,7 @@ def _add_functionality():
         err = None
         try:
             self._build(options=options, devices=devices)
-        except Exception, e:
+        except Exception as e:
             from pytools import Record
 
             class ErrorRecord(Record):
@@ -504,7 +509,7 @@ def _add_functionality():
         if kwargs:
             raise TypeError(
                     "Kernel.__call__ recived unexpected keyword arguments: %s"
-                    % ", ".join(kwargs.keys()))
+                    % ", ".join(list(kwargs.keys())))
 
         self.set_args(*args)
 
@@ -549,7 +554,7 @@ def _add_functionality():
                         self.set_arg(i, pack(arg_type_char, arg))
                     else:
                         self.set_arg(i, arg)
-        except LogicError, e:
+        except LogicError as e:
             if i is not None:
                 advice = ""
                 from pyopencl.array import Array
@@ -796,7 +801,7 @@ def create_some_context(interactive=None, answers=None):
 
     def cc_print(s):
         if interactive:
-            print s
+            print(s)
 
     def get_input(prompt):
         if answers:
@@ -804,7 +809,7 @@ def create_some_context(interactive=None, answers=None):
         elif not interactive:
             return ''
         else:
-            user_input = raw_input(prompt)
+            user_input = input(prompt)
             user_inputs.append(user_input)
             return user_input
 
diff --git a/pyopencl/_mymako.py b/pyopencl/_mymako.py
index a4e4b46505c013d7d28058afeace5834e56f53d5..ce6943fb634ddbcd06fea2f7c3e1016648d23c3c 100644
--- a/pyopencl/_mymako.py
+++ b/pyopencl/_mymako.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 try:
     import mako.template
 except ImportError:
diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py
index 0fb9c611a93f43610298c66533a80e9572fe44fc..e0533a2d2c3ed9f43bcf75a1d77d31d0a0815844 100644
--- a/pyopencl/algorithm.py
+++ b/pyopencl/algorithm.py
@@ -1,6 +1,9 @@
 """Scan primitive."""
 
 from __future__ import division
+from __future__ import absolute_import
+from six.moves import range
+from six.moves import zip
 
 __copyright__ = """Copyright 2011-2012 Andreas Kloeckner"""
 
diff --git a/pyopencl/array.py b/pyopencl/array.py
index bd2ee902ea179e4ec39db06884ac14ecd3f84d1f..4592cc1e4fa11db6ed1b617616225a47edb2645d 100644
--- a/pyopencl/array.py
+++ b/pyopencl/array.py
@@ -1,6 +1,11 @@
 """CL device arrays."""
 
 from __future__ import division
+from __future__ import absolute_import
+import six
+from six.moves import range
+from six.moves import zip
+from functools import reduce
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
@@ -129,7 +134,7 @@ def _create_vector_types():
                 array = eval("array(padded_args, dtype=dtype)",
                         dict(array=np.array, padded_args=padded_args,
                         dtype=dtype))
-                for key, val in kwargs.items():
+                for key, val in list(kwargs.items()):
                     array[key] = val
                 return array
 
@@ -159,7 +164,7 @@ def splay(queue, n, kernel_specific_max_wg_size=None):
     max_work_items = _builtin_min(128, dev.max_work_group_size)
 
     if kernel_specific_max_wg_size is not None:
-        from __builtin__ import min
+        from six.moves.builtins import min
         max_work_items = min(max_work_items, kernel_specific_max_wg_size)
 
     min_work_items = _builtin_min(32, max_work_items)
@@ -512,7 +517,7 @@ class Array(object):
             if sys.version_info >= (3,):
                 admissible_types = (int, np.integer)
             else:
-                admissible_types = (int, long, np.integer)
+                admissible_types = (np.integer,) + six.integer_types
 
             if not isinstance(shape, admissible_types):
                 raise TypeError("shape must either be iterable or "
@@ -1286,7 +1291,7 @@ class Array(object):
         order = kwargs.pop("order", "C")
         if kwargs:
             raise TypeError("unexpected keyword arguments: %s"
-                    % kwargs.keys())
+                    % list(kwargs.keys()))
 
         if order not in "CF":
             raise ValueError("order must be either 'C' or 'F'")
@@ -1369,7 +1374,7 @@ class Array(object):
             # Calculate new strides for all axes currently worked with
             if order == "F":
                 newstrides[ni] = oldstrides[oi]
-                for nk in xrange(ni+1, nj):
+                for nk in range(ni+1, nj):
                     newstrides[nk] = newstrides[nk - 1]*newdims[nk - 1]
             else:
                 # C order
@@ -1780,7 +1785,7 @@ def arange(queue, *args, **kwargs):
         raise ValueError("too many arguments")
 
     admissible_names = ["start", "stop", "step", "dtype", "allocator"]
-    for k, v in kwargs.iteritems():
+    for k, v in six.iteritems(kwargs):
         if k in admissible_names:
             if getattr(inf, k) is None:
                 setattr(inf, k, v)
diff --git a/pyopencl/cache.py b/pyopencl/cache.py
index 6d054648ae5cc84530c61ffc85744a36780444a2..2b38c07302796ae60cc9ef630eb5f5dddaa3ddad 100644
--- a/pyopencl/cache.py
+++ b/pyopencl/cache.py
@@ -1,6 +1,9 @@
 """PyOpenCL compiler cache."""
 
 from __future__ import division
+from __future__ import absolute_import
+import six
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2011 Andreas Kloeckner"
 
@@ -48,7 +51,7 @@ def _erase_dir(dir):
 
 
 def update_checksum(checksum, obj):
-    if isinstance(obj, unicode):
+    if isinstance(obj, six.text_type):
         checksum.update(obj.encode("utf8"))
     else:
         checksum.update(obj)
@@ -192,7 +195,7 @@ def get_dependencies(src, include_path):
 
     _inner(src)
 
-    result = list((name,) + vals for name, vals in result.iteritems())
+    result = list((name,) + vals for name, vals in six.iteritems(result))
     result.sort()
 
     return result
@@ -265,7 +268,7 @@ def retrieve_from_cache(cache_dir, cache_key):
             # {{{ load info file
 
             try:
-                from cPickle import load
+                from six.moves.cPickle import load
 
                 try:
                     info_file = open(info_path, "rb")
@@ -346,7 +349,7 @@ def _create_built_program_from_source_cached(ctx, src, options, devices, cache_d
 
     try:
         os.makedirs(cache_dir)
-    except OSError, e:
+    except OSError as e:
         from errno import EEXIST
         if e.errno != EEXIST:
             raise
@@ -448,7 +451,7 @@ def _create_built_program_from_source_cached(ctx, src, options, devices, cache_d
                     outf.write(binary)
                     outf.close()
 
-                    from cPickle import dump
+                    from six.moves.cPickle import dump
                     info_file = open(info_path, "wb")
                     dump(_SourceInfo(
                         dependencies=get_dependencies(src, include_path),
@@ -476,7 +479,7 @@ def create_built_program_from_source_cached(ctx, src, options=[], devices=None,
             prg = _cl._Program(ctx, src)
             already_built = False
 
-    except Exception, e:
+    except Exception as e:
         raise
         from pyopencl import Error
         if (isinstance(e, Error)
diff --git a/pyopencl/capture_call.py b/pyopencl/capture_call.py
index cc4539b224075d969662e856030268e8f1560c67..bf0615679798de1e9969fab4eb8e99592bf2e688 100644
--- a/pyopencl/capture_call.py
+++ b/pyopencl/capture_call.py
@@ -1,4 +1,6 @@
 from __future__ import with_statement, division
+from __future__ import absolute_import
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2013 Andreas Kloeckner"
 
diff --git a/pyopencl/characterize/__init__.py b/pyopencl/characterize/__init__.py
index 26e5b994bc2a265e1e6805d79b59e688ee7f31a8..a671c09507855af15f4b24c35dfb9feba3ff2c1b 100644
--- a/pyopencl/characterize/__init__.py
+++ b/pyopencl/characterize/__init__.py
@@ -1,4 +1,8 @@
 from __future__ import division
+from __future__ import absolute_import
+import six
+from six.moves import range
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
@@ -211,7 +215,7 @@ def why_not_local_access_conflict_free(dev, itemsize,
     for work_item_axis in range(rank):
 
         bank_accesses = {}
-        for work_item_id in xrange(sim_wi):
+        for work_item_id in range(sim_wi):
             addr = 0
             addr_mult = itemsize
 
@@ -238,10 +242,10 @@ def why_not_local_access_conflict_free(dev, itemsize,
                     "w.item %s -> %s" % (work_item_id, idx[::-1]))
 
         conflict_multiplicity = max(
-                len(acc) for acc in bank_accesses.itervalues())
+                len(acc) for acc in six.itervalues(bank_accesses))
 
         if conflict_multiplicity > 1:
-            for bank, acc in bank_accesses.iteritems():
+            for bank, acc in six.iteritems(bank_accesses):
                 if len(acc) == conflict_multiplicity:
                     conflicts.append(
                             (conflict_multiplicity,
diff --git a/pyopencl/characterize/performance.py b/pyopencl/characterize/performance.py
index e498582e8dd26d2ddb496038780b144adf9482cd..d2cbf791ecde610c5a5e6fc69bad7d0dff37d213 100644
--- a/pyopencl/characterize/performance.py
+++ b/pyopencl/characterize/performance.py
@@ -1,4 +1,7 @@
 from __future__ import division
+from __future__ import absolute_import
+from __future__ import print_function
+from six.moves import range
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
@@ -77,12 +80,12 @@ def _get_time(queue, f, timer_factory=None, desired_duration=0.1,
     while True:
         timer = timer_factory(queue)
 
-        for i in xrange(warmup_rounds):
+        for i in range(warmup_rounds):
             f()
         warmup_rounds = 0
 
         timer.start()
-        for i in xrange(count):
+        for i in range(count):
             timer.add_event(f())
         timer.stop()
 
@@ -191,7 +194,7 @@ def _get_full_machine_kernel_rate(queue, src, args, name="benchmark", timer_fact
     while True:
         elapsed = _get_time(queue, f, timer_factory=timer_factory)
         rate = global_size/elapsed
-        print global_size, rate, num_dips
+        print(global_size, rate, num_dips)
 
         keep_trying = not rates
 
diff --git a/pyopencl/clmath.py b/pyopencl/clmath.py
index d745741d2091264058d7dc1c29275db110e948e6..bbe4524d7368a22a657567225a523c9924a50024 100644
--- a/pyopencl/clmath.py
+++ b/pyopencl/clmath.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
 __license__ = """
diff --git a/pyopencl/clrandom.py b/pyopencl/clrandom.py
index 13cfbc20ff4a8857be53bef7db83a71fb8a5616a..f28e1770d991fe4111b4c94aee508637539d5167 100644
--- a/pyopencl/clrandom.py
+++ b/pyopencl/clrandom.py
@@ -1,5 +1,6 @@
 # encoding: utf8
 from __future__ import division
+from __future__ import absolute_import
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
diff --git a/pyopencl/elementwise.py b/pyopencl/elementwise.py
index 47fe3d9585b1aebf08cde69624066e5088a081ae..91e3774c89ad4945ffbdf5e44db61091167a4d1b 100644
--- a/pyopencl/elementwise.py
+++ b/pyopencl/elementwise.py
@@ -1,6 +1,9 @@
 """Elementwise functionality."""
 
 from __future__ import division
+from __future__ import absolute_import
+from six.moves import range
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
diff --git a/pyopencl/ipython_ext.py b/pyopencl/ipython_ext.py
index bedbf77f039ba2f04280239ec13d274a10a3e82a..ce80fc07a8b774996f0154f34fec24d2d2b98e1f 100644
--- a/pyopencl/ipython_ext.py
+++ b/pyopencl/ipython_ext.py
@@ -1,13 +1,15 @@
 from __future__ import division
+from __future__ import absolute_import
 
 from IPython.core.magic import (magics_class, Magics, cell_magic, line_magic)
 
 import pyopencl as cl
 import sys
+import six
 
 
 def _try_to_utf8(text):
-    if isinstance(text, unicode):
+    if isinstance(text, six.text_type):
         return text.encode("utf8")
     return text
 
diff --git a/pyopencl/reduction.py b/pyopencl/reduction.py
index 2e432fc5572f9cc37001011d3dbbbef2bf3acdcd..689763f17ef733aa2dc0a2421d625459b2661458 100644
--- a/pyopencl/reduction.py
+++ b/pyopencl/reduction.py
@@ -1,6 +1,8 @@
 """Computation of reductions on vectors."""
 
 from __future__ import division
+from __future__ import absolute_import
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2010 Andreas Kloeckner"
 
diff --git a/pyopencl/scan.py b/pyopencl/scan.py
index 10a64ee57e8d844723a584ce1795da530902c073..0ca0aa6a2c1d904a956cbd2e0bb8f3d71a69c726 100644
--- a/pyopencl/scan.py
+++ b/pyopencl/scan.py
@@ -1,6 +1,10 @@
 """Scan primitive."""
 
 from __future__ import division
+from __future__ import absolute_import
+import six
+from six.moves import range
+from six.moves import zip
 
 __copyright__ = """
 Copyright 2011-2012 Andreas Kloeckner
@@ -1237,7 +1241,7 @@ class GenericScanKernel(_GenericScanKernelBase):
 
                 + k_group_size*wg_size*sum(
                     arg_dtypes[arg_name].itemsize
-                    for arg_name, ife_offsets in fetch_expr_offsets.items()
+                    for arg_name, ife_offsets in list(fetch_expr_offsets.items())
                     if -1 in ife_offsets or len(ife_offsets) > 1))
 
     def build_scan_kernel(self, max_wg_size, arguments, input_expr,
@@ -1536,7 +1540,7 @@ class _LegacyScanKernelBase(GenericScanKernel):
         if output_ary is None:
             output_ary = input_ary
 
-        if isinstance(output_ary, (str, unicode)) and output_ary == "new":
+        if isinstance(output_ary, (str, six.text_type)) and output_ary == "new":
             output_ary = cl.array.empty_like(input_ary, allocator=allocator)
 
         if input_ary.shape != output_ary.shape:
diff --git a/pyopencl/tools.py b/pyopencl/tools.py
index 32aa8e64cd8a33134bcb9d694b4d830f134cedcc..0a3db037b6f7a03ae2d21280d847ecc6a49b4203 100644
--- a/pyopencl/tools.py
+++ b/pyopencl/tools.py
@@ -1,6 +1,9 @@
 """Various helpful bits and pieces without much of a common theme."""
 
 from __future__ import division
+from __future__ import absolute_import
+import six
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2010 Andreas Kloeckner"
 
@@ -134,8 +137,8 @@ def first_arg_dependent_memoize_nested(nested_func):
 
     from functools import wraps
     cache_dict_name = intern("_memoize_inner_dic_%s_%s_%d"
-            % (nested_func.__name__, nested_func.func_code.co_filename,
-                nested_func.func_code.co_firstlineno))
+            % (nested_func.__name__, nested_func.__code__.co_filename,
+                nested_func.__code__.co_firstlineno))
 
     from inspect import currentframe
     # prevent ref cycle
@@ -286,7 +289,7 @@ def pytest_generate_tests_for_pyopencl(metafunc):
 
                 metafunc.addcall(funcargs=arg_dict.copy(),
                         id=", ".join("%s=%s" % (arg, value)
-                                for arg, value in arg_dict.iteritems()))
+                                for arg, value in six.iteritems(arg_dict)))
 
     elif "platform" in metafunc.funcargnames:
         for platform, plat_devs in test_plat_and_dev:
@@ -474,7 +477,7 @@ class _CDeclList:
         if dtype in vec.type_to_scalar_and_count:
             return
 
-        for name, field_data in dtype.fields.iteritems():
+        for name, field_data in six.iteritems(dtype.fields):
             field_dtype, offset = field_data[:2]
             self.add_dtype(field_dtype)
 
@@ -552,8 +555,8 @@ def match_dtype_to_c_struct(device, name, dtype, context=None):
     function, not the original one.
     """
 
-    fields = sorted(dtype.fields.iteritems(),
-            key=lambda (name, (dtype, offset)): offset)
+    fields = sorted(six.iteritems(dtype.fields),
+            key=lambda name_dtype_offset: name_dtype_offset[1][1])
 
     c_fields = []
     for field_name, (field_dtype, offset) in fields:
@@ -671,7 +674,7 @@ def dtype_to_c_struct(device, dtype):
     def dtypes_match():
         result = len(dtype.fields) == len(matched_dtype.fields)
 
-        for name, val in dtype.fields.iteritems():
+        for name, val in six.iteritems(dtype.fields):
             result = result and matched_dtype.fields[name] == val
 
         return result
@@ -848,12 +851,12 @@ class _TemplateRenderer(object):
         if arguments is not None:
             cdl.visit_arguments(arguments)
 
-        for tv in self.type_aliases.itervalues():
+        for tv in six.itervalues(self.type_aliases):
             cdl.add_dtype(tv)
 
         type_alias_decls = [
                 "typedef %s %s;" % (dtype_to_ctype(val), name)
-                for name, val in self.type_aliases.iteritems()
+                for name, val in six.iteritems(self.type_aliases)
                 ]
 
         return cdl.get_declarations() + "\n" + "\n".join(type_alias_decls)
@@ -899,7 +902,7 @@ class KernelTemplateBase(object):
     def build(self, context, *args, **kwargs):
         """Provide caching for an :meth:`build_inner`."""
 
-        cache_key = (context, args, tuple(sorted(kwargs.iteritems())))
+        cache_key = (context, args, tuple(sorted(six.iteritems(kwargs))))
         try:
             return self.build_cache[cache_key]
         except KeyError:
diff --git a/setup.py b/setup.py
index 24248cc4495dbb9c2e79cefe1664dd75c6b581a5..27e9636d8157380af71e563f32c857990a31e3a2 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+from __future__ import print_function
 #!/usr/bin/env python
 # -*- coding: latin-1 -*-
 
@@ -109,11 +111,6 @@ def main():
     exec(compile(version_file_contents, "pyopencl/version.py", 'exec'), ver_dic)
 
     SEPARATOR = "-"*75
-    try:
-        from distutils.command.build_py import build_py_2to3 as build_py
-    except ImportError:
-        # 2.x
-        from distutils.command.build_py import build_py
 
     try:
         import mako  # noqa
@@ -246,8 +243,6 @@ def main():
                         ]
                     },
 
-            # 2to3 invocation
-            cmdclass={'build_py': build_py},
             zip_safe=False)
 
 
diff --git a/test/test_algorithm.py b/test/test_algorithm.py
index 06a9258032920bee78ee4d56c650c0cbb830eb83..88c3097bdbbb3e5c96ab1de1d868dbcef0eddc33 100644
--- a/test/test_algorithm.py
+++ b/test/test_algorithm.py
@@ -1,6 +1,10 @@
 #! /usr/bin/env python
 
 from __future__ import division, with_statement
+from __future__ import absolute_import
+from __future__ import print_function
+from six.moves import range
+from six.moves import zip
 
 __copyright__ = "Copyright (C) 2013 Andreas Kloeckner"
 
diff --git a/test/test_array.py b/test/test_array.py
index acb82ec8876b0b96867379f9c129a24c3d15ccb9..f5112eaeb2a38f4a924f7782e056e064bfc51ad2 100644
--- a/test/test_array.py
+++ b/test/test_array.py
@@ -1,5 +1,8 @@
 #! /usr/bin/env python
 from __future__ import division, with_statement
+from __future__ import absolute_import
+from __future__ import print_function
+from six.moves import range
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
diff --git a/test/test_clmath.py b/test/test_clmath.py
index 53f017e49bfda6b5330b001ef7f9558a3be7cb53..9c322cdf4b6cc8f1d18697da098b841444b48984 100644
--- a/test/test_clmath.py
+++ b/test/test_clmath.py
@@ -1,4 +1,6 @@
 from __future__ import division, print_function
+from __future__ import absolute_import
+from six.moves import range
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
 
diff --git a/test/test_wrapper.py b/test/test_wrapper.py
index 870e3c5d946f321cbe93730369f17b26da5d44c4..01382ec61648b8e3ed74cc75b42d4bdc450f922f 100644
--- a/test/test_wrapper.py
+++ b/test/test_wrapper.py
@@ -1,4 +1,7 @@
 from __future__ import division
+from __future__ import absolute_import
+from __future__ import print_function
+from six.moves import range
 
 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"