diff --git a/IPython/core/formatters.py b/IPython/core/formatters.py
index 895b419..195664c 100644
--- a/IPython/core/formatters.py
+++ b/IPython/core/formatters.py
@@ -27,8 +27,6 @@ Authors:
 import abc
 import sys
 import warnings
-# We must use StringIO, as cStringIO doesn't handle unicode properly.
-from io import StringIO
 
 # Our own imports
 from IPython.config.configurable import Configurable
@@ -36,7 +34,12 @@ from IPython.lib import pretty
 from IPython.utils.traitlets import (
     Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
 )
-from IPython.utils.py3compat import unicode_to_str, with_metaclass
+from IPython.utils.py3compat import unicode_to_str, with_metaclass, PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 
 #-----------------------------------------------------------------------------
diff --git a/IPython/core/inputtransformer.py b/IPython/core/inputtransformer.py
index c2b9647..115a5ca 100644
--- a/IPython/core/inputtransformer.py
+++ b/IPython/core/inputtransformer.py
@@ -1,14 +1,18 @@
 import abc
 import functools
 import re
-from io import StringIO
 
 from IPython.core.splitinput import LineInfo
 from IPython.utils import tokenize2
 from IPython.utils.openpy import cookie_comment_re
-from IPython.utils.py3compat import with_metaclass
+from IPython.utils.py3compat import with_metaclass, PY3
 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
 
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
+
 #-----------------------------------------------------------------------------
 # Globals
 #-----------------------------------------------------------------------------
diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py
index 6c2d86e..8921e63 100644
--- a/IPython/core/magics/execution.py
+++ b/IPython/core/magics/execution.py
@@ -20,7 +20,6 @@ import bdb
 import os
 import sys
 import time
-from io import StringIO
 
 # cProfile was added in Python2.5
 try:
@@ -43,7 +42,7 @@ from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
                                 line_cell_magic, on_off, needs_local_scope)
 from IPython.testing.skipdoctest import skip_doctest
 from IPython.utils import py3compat
-from IPython.utils.py3compat import builtin_mod, iteritems
+from IPython.utils.py3compat import builtin_mod, iteritems, PY3
 from IPython.utils.contexts import preserve_keys
 from IPython.utils.io import capture_output
 from IPython.utils.ipstruct import Struct
@@ -52,6 +51,10 @@ from IPython.utils.path import get_py_filename, unquote_filename, shellglob
 from IPython.utils.timing import clock, clock2
 from IPython.utils.warn import warn, error
 
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Magic implementation classes
diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py
index 3b7acfd..4ac9821 100644
--- a/IPython/core/tests/test_interactiveshell.py
+++ b/IPython/core/tests/test_interactiveshell.py
@@ -28,7 +28,6 @@ import sys
 import tempfile
 import unittest
 from os.path import join
-from io import StringIO
 
 # third-party
 import nose.tools as nt
@@ -37,7 +36,12 @@ import nose.tools as nt
 from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths
 from IPython.testing import tools as tt
 from IPython.utils import io
-from IPython.utils.py3compat import unicode_type
+from IPython.utils.py3compat import unicode_type, PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Globals
diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py
index ae0cf0e..09b6486 100644
--- a/IPython/core/tests/test_magic.py
+++ b/IPython/core/tests/test_magic.py
@@ -12,7 +12,6 @@ from __future__ import absolute_import
 import io
 import os
 import sys
-from io import StringIO
 from unittest import TestCase
 
 try:
@@ -38,6 +37,11 @@ from IPython.utils.io import capture_output
 from IPython.utils.tempdir import TemporaryDirectory
 from IPython.utils.process import find_cmd
 
+if py3compat.PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
+
 #-----------------------------------------------------------------------------
 # Test functions begin
 #-----------------------------------------------------------------------------
diff --git a/IPython/extensions/tests/test_autoreload.py b/IPython/extensions/tests/test_autoreload.py
index aac6ee9..8ada638 100644
--- a/IPython/extensions/tests/test_autoreload.py
+++ b/IPython/extensions/tests/test_autoreload.py
@@ -18,13 +18,18 @@ import tempfile
 import shutil
 import random
 import time
-from io import StringIO
 
 import nose.tools as nt
 import IPython.testing.tools as tt
 
 from IPython.extensions.autoreload import AutoreloadMagics
 from IPython.core.hooks import TryNext
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Test fixture
diff --git a/IPython/extensions/tests/test_rmagic.py b/IPython/extensions/tests/test_rmagic.py
index 55817b2..501f74e 100644
--- a/IPython/extensions/tests/test_rmagic.py
+++ b/IPython/extensions/tests/test_rmagic.py
@@ -1,11 +1,15 @@
-from io import StringIO
-
 import numpy as np
 from IPython.testing.decorators import skip_without
 from IPython.extensions import rmagic
+from IPython.utils.py3compat import PY3
 from rpy2 import rinterface
 import nose.tools as nt
 
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
+
 ip = get_ipython()
 ip.magic('load_ext rmagic')
 
diff --git a/IPython/kernel/inprocess/tests/test_kernel.py b/IPython/kernel/inprocess/tests/test_kernel.py
index cdcdbf9..e817d3a 100644
--- a/IPython/kernel/inprocess/tests/test_kernel.py
+++ b/IPython/kernel/inprocess/tests/test_kernel.py
@@ -11,7 +11,6 @@
 from __future__ import print_function
 
 # Standard library imports
-from io import StringIO
 import sys
 import unittest
 
@@ -23,6 +22,11 @@ from IPython.testing.decorators import skipif_not_matplotlib
 from IPython.utils.io import capture_output
 from IPython.utils import py3compat
 
+if py3compat.PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
+
 #-----------------------------------------------------------------------------
 # Test case
 #-----------------------------------------------------------------------------
diff --git a/IPython/lib/pretty.py b/IPython/lib/pretty.py
index 8e1b1b8..20cf5b8 100644
--- a/IPython/lib/pretty.py
+++ b/IPython/lib/pretty.py
@@ -109,9 +109,15 @@ import sys
 import types
 import re
 import datetime
-from io import StringIO
 from collections import deque
 
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
+
 
 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
     'for_type', 'for_type_by_name']
diff --git a/IPython/lib/tests/test_irunner.py b/IPython/lib/tests/test_irunner.py
index 527d5fb..cb8a7aa 100644
--- a/IPython/lib/tests/test_irunner.py
+++ b/IPython/lib/tests/test_irunner.py
@@ -8,19 +8,23 @@ from __future__ import print_function
 VERBOSE = True
 
 # stdlib imports
-import io
 import sys
 import unittest
 
 # IPython imports
 from IPython.lib import irunner
-from IPython.utils.py3compat import doctest_refactor_print
+from IPython.utils.py3compat import doctest_refactor_print, PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 # Testing code begins
 class RunnerTestCase(unittest.TestCase):
 
     def setUp(self):
-        self.out = io.StringIO()
+        self.out = StringIO()
         #self.out = sys.stdout
 
     def _test_runner(self,runner,source,output):
diff --git a/IPython/lib/tests/test_irunner_pylab_magic.py b/IPython/lib/tests/test_irunner_pylab_magic.py
index 31d4f02..adbeff3 100644
--- a/IPython/lib/tests/test_irunner_pylab_magic.py
+++ b/IPython/lib/tests/test_irunner_pylab_magic.py
@@ -7,7 +7,6 @@ from __future__ import print_function
 VERBOSE = True
 
 # stdlib imports
-import io
 import sys
 import unittest
 import re
@@ -15,6 +14,12 @@ import re
 # IPython imports
 from IPython.lib import irunner
 from IPython.testing import decorators
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 def pylab_not_importable():
     """Test if importing pylab fails. (For example, when having no display)"""
@@ -28,7 +33,7 @@ def pylab_not_importable():
 class RunnerTestCase(unittest.TestCase):
 
     def setUp(self):
-        self.out = io.StringIO()
+        self.out = StringIO()
         #self.out = sys.stdout
 
     def _test_runner(self,runner,source,output):
diff --git a/IPython/nbconvert/writers/tests/test_debug.py b/IPython/nbconvert/writers/tests/test_debug.py
index 08ab03e..81bf4f5 100644
--- a/IPython/nbconvert/writers/tests/test_debug.py
+++ b/IPython/nbconvert/writers/tests/test_debug.py
@@ -15,10 +15,15 @@ Module with tests for debug
 #-----------------------------------------------------------------------------
 
 import sys
-from io import StringIO
 
 from ...tests.base import TestsBase
 from ..debug import DebugWriter
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 
 #-----------------------------------------------------------------------------
diff --git a/IPython/nbconvert/writers/tests/test_files.py b/IPython/nbconvert/writers/tests/test_files.py
index 02296b8..603e4a5 100644
--- a/IPython/nbconvert/writers/tests/test_files.py
+++ b/IPython/nbconvert/writers/tests/test_files.py
@@ -16,10 +16,15 @@ Module with tests for files
 
 import sys
 import os
-from io import StringIO
 
 from ...tests.base import TestsBase
 from ..files import FilesWriter
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 
 #-----------------------------------------------------------------------------
diff --git a/IPython/nbconvert/writers/tests/test_stdout.py b/IPython/nbconvert/writers/tests/test_stdout.py
index 4d97f9e..4b9add0 100644
--- a/IPython/nbconvert/writers/tests/test_stdout.py
+++ b/IPython/nbconvert/writers/tests/test_stdout.py
@@ -15,10 +15,15 @@ Module with tests for stdout
 #-----------------------------------------------------------------------------
 
 import sys
-from io import StringIO
 
 from ...tests.base import TestsBase
 from ..stdout import StdoutWriter
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 
 #-----------------------------------------------------------------------------
diff --git a/IPython/parallel/tests/clienttest.py b/IPython/parallel/tests/clienttest.py
index 5e897c5..28cd73d 100644
--- a/IPython/parallel/tests/clienttest.py
+++ b/IPython/parallel/tests/clienttest.py
@@ -16,7 +16,6 @@ from __future__ import print_function
 import sys
 import tempfile
 import time
-from io import StringIO
 
 from nose import SkipTest
 
diff --git a/IPython/sphinxext/ipython_directive.py b/IPython/sphinxext/ipython_directive.py
index df0342f..17c3c65 100644
--- a/IPython/sphinxext/ipython_directive.py
+++ b/IPython/sphinxext/ipython_directive.py
@@ -58,7 +58,6 @@ from __future__ import print_function
 #-----------------------------------------------------------------------------
 
 # Stdlib
-import io
 import os
 import re
 import sys
@@ -84,6 +83,12 @@ matplotlib.use('Agg')
 from IPython import Config, InteractiveShell
 from IPython.core.profiledir import ProfileDir
 from IPython.utils import io
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Globals
@@ -193,7 +198,7 @@ class EmbeddedSphinxShell(object):
 
     def __init__(self):
 
-        self.cout = io.StringIO()
+        self.cout = StringIO()
 
 
         # Create config object for IPython
diff --git a/IPython/testing/plugin/ipdoctest.py b/IPython/testing/plugin/ipdoctest.py
index ffff4d1..42438c5 100644
--- a/IPython/testing/plugin/ipdoctest.py
+++ b/IPython/testing/plugin/ipdoctest.py
@@ -29,7 +29,6 @@ import traceback
 import unittest
 
 from inspect import getmodule
-from io import StringIO
 
 # We are overriding the default doctest runner, so we need to import a few
 # things from doctest directly
@@ -46,7 +45,12 @@ from nose.plugins import doctests, Plugin
 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
 
 # Our own imports
-from IPython.utils.py3compat import builtin_mod
+from IPython.utils.py3compat import builtin_mod, PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Module globals and other constants
diff --git a/IPython/utils/PyColorize.py b/IPython/utils/PyColorize.py
index aaafcfa..aec5231 100644
--- a/IPython/utils/PyColorize.py
+++ b/IPython/utils/PyColorize.py
@@ -38,7 +38,6 @@ _scheme_default = 'Linux'
 
 
 # Imports
-import io
 import keyword
 import os
 import sys
@@ -53,6 +52,12 @@ except AttributeError:
     generate_tokens = tokenize._tokenize
 
 from IPython.utils.coloransi import *
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #############################################################################
 ### Python Source Parser (does Hilighting)
@@ -143,13 +148,13 @@ class Parser:
 
         string_output = 0
         if out == 'str' or self.out == 'str' or \
-           isinstance(self.out,io.StringIO):
+           isinstance(self.out,StringIO):
             # XXX - I don't really like this state handling logic, but at this
             # point I don't want to make major changes, so adding the
             # isinstance() check is the simplest I can do to ensure correct
             # behavior.
             out_old = self.out
-            self.out = io.StringIO()
+            self.out = StringIO()
             string_output = 1
         elif out is not None:
             self.out = out
@@ -183,7 +188,7 @@ class Parser:
 
         # parse the source and write it
         self.pos = 0
-        text = io.StringIO(self.raw)
+        text = StringIO(self.raw)
 
         error = False
         try:
diff --git a/IPython/utils/capture.py b/IPython/utils/capture.py
index a871d96..01ad4e8 100644
--- a/IPython/utils/capture.py
+++ b/IPython/utils/capture.py
@@ -16,7 +16,13 @@ from __future__ import print_function, absolute_import
 #-----------------------------------------------------------------------------
 
 import sys
-from io import StringIO
+
+from IPython.utils.py3compat import PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Classes and functions
diff --git a/IPython/utils/tests/test_io.py b/IPython/utils/tests/test_io.py
index c3a099c..4818c07 100644
--- a/IPython/utils/tests/test_io.py
+++ b/IPython/utils/tests/test_io.py
@@ -15,14 +15,18 @@ from __future__ import print_function
 
 import sys
 
-from io import StringIO
 from subprocess import Popen, PIPE
 import unittest
 
 import nose.tools as nt
 
 from IPython.utils.io import Tee, capture_output
-from IPython.utils.py3compat import doctest_refactor_print
+from IPython.utils.py3compat import doctest_refactor_print, PY3
+
+if PY3:
+    from io import StringIO
+else:
+    from StringIO import StringIO
 
 #-----------------------------------------------------------------------------
 # Tests