diff --git a/demo/df.py b/demo/df.py
index f95e1c2695bfee34474d95c7752201d632560cd2..72c00b37baebaff795848a0bb3ef222f622bfdf7 100644
--- a/demo/df.py
+++ b/demo/df.py
@@ -23,21 +23,21 @@ df = Popen("df -k")
 x = Controller()
 while x.loop():
     if x.re(df, "Filesystem.*\n"):
-        print "Header:", df.match.group()
+        print("Header:", df.match.group())
         break
 
 x = Controller()
 while x.loop():
     if x.re(df, "^/.* .*(?=\n)"):
-        print "Normal line:", df.match.group()
+        print("Normal line:", df.match.group())
     elif x.re(df, "^/.*(?=\n)"):
-        print "Mount point only:", df.match.group()
+        print("Mount point only:", df.match.group())
     elif x.re(df, "^ .*(?=\n)"):
-        print "Info only:", df.match.group()
+        print("Info only:", df.match.group())
     elif x.re(df, "^\n"):
         pass
     elif x.re(df, "^.*(?=\n)"):
-        print "Unexpected line", df.match.group()
+        print("Unexpected line", df.match.group())
     elif x.eof(df):
-        print "And that's all, folks!"
+        print("And that's all, folks!")
         break
diff --git a/demo/dualftp.py b/demo/dualftp.py
index be1cf0cedc81f7cb309ba7c6d950f82b12a58bf3..446a84c8f7f5d00eed8517bfd7d12b1e05122140 100644
--- a/demo/dualftp.py
+++ b/demo/dualftp.py
@@ -55,7 +55,7 @@ def prompt_cb(ftp):
         ftp.send(cmds[ftp][0])
         cmds[ftp] = cmds[ftp][1:]
     else:
-        print ftp.match.group()
+        print(ftp.match.group())
         printed += 1
         speed[ftp] = time.time() - time0
             
@@ -86,7 +86,7 @@ pcl_expect.expect_after([])
 x = pcl_expect.Controller()
 while x.loop():
     if x.eof(sunet):
-        print "SUNET final output:", sunet.consumed
+        print("SUNET final output:", sunet.consumed)
         sunet.close()
         break
     elif x.timeout():
@@ -96,12 +96,12 @@ while x.loop():
 x = pcl_expect.Controller()
 while x.loop():
     if x.eof(funet):
-        print "FUNET final output:", funet.consumed
+        print("FUNET final output:", funet.consumed)
         funet.close()
         break
     elif x.timeout():
         sys.stdout.write(".")
         sys.stdout.flush()
 
-print "SUNET time:", speed[sunet], "seconds"
-print "FUNET time:", speed[funet], "seconds"
+print("SUNET time:", speed[sunet], "seconds")
+print("FUNET time:", speed[funet], "seconds")
diff --git a/demo/ftp.py b/demo/ftp.py
index e26286b30d81b8047e4b44818dd8a0d25b5003f0..f3a71bfe64c9fa11efaf3c46a05753c17dfcb317 100644
--- a/demo/ftp.py
+++ b/demo/ftp.py
@@ -50,7 +50,7 @@ ftp.send("dir\n")
 x = pcl_expect.Controller()
 while x.loop():
     if x.re(ftp, "(?s).*ftp> "):
-        print ftp.match.group()
+        print(ftp.match.group())
         break
 
 ftp.close()
diff --git a/demo/ftptrad.py b/demo/ftptrad.py
index a8fed7d1d54d99954197f2bbf6abd6d97e902a1a..3054ace8a14ea2ede2bd653bb65b0e83517f0ffc 100644
--- a/demo/ftptrad.py
+++ b/demo/ftptrad.py
@@ -51,6 +51,6 @@ ftp.send("dir\n")
 
 ret, exp = pcl_expect.expect([(pcl_expect.RE, ftp, "(?s).*ftp> ")])
 if ret == 0:
-    print ftp.match.group()
+    print(ftp.match.group())
 
 ftp.close()
diff --git a/demo/komtime.py b/demo/komtime.py
index f4949e5c7123263ab8a64691e6fa97efee4e6ace..298293ba40bfb8b8014034411c000a2349f2cb08 100644
--- a/demo/komtime.py
+++ b/demo/komtime.py
@@ -46,8 +46,8 @@ while x.loop():
                   "\n")):
         year, month, day, hour, min, sec = [int(x) for x in kom.match.group(
             "year", "month", "day", "hour", "min", "sec")]
-        print "%4d-%02d-%02d %02d:%02d:%02d (according to the server)" % (
-            1900+year, 1+month, day, hour, min, sec)
+        print("%4d-%02d-%02d %02d:%02d:%02d (according to the server)" % (
+            1900+year, 1+month, day, hour, min, sec))
         break
 
 kom.send("1 55 0\n")
@@ -59,7 +59,7 @@ while x.loop():
         pass
     elif x.eof(kom):
         if kom.consumed != "":
-            print "Unexpected output:", kom.consumed
+            print("Unexpected output:", kom.consumed)
         break
 
 kom.close()
diff --git a/demo/read-serial.py b/demo/read-serial.py
index bc24d48df822b24c375f40a2678e62ffc17a5b37..85554ef57d008651bff9b87e78ebe0744b949c88 100644
--- a/demo/read-serial.py
+++ b/demo/read-serial.py
@@ -27,9 +27,9 @@ port = pcl_expect.pyserial.Serial(0, baudrate=4800)
 x = pcl_expect.Controller()
 while x.loop():
     if x.re(port, "..*"):
-        print "Got", repr(port.consumed)
+        print("Got", repr(port.consumed))
     elif x.timeout():
-        print "Timeout"
+        print("Timeout")
         break
 
 port.close()
diff --git a/demo/stderr.py b/demo/stderr.py
index 07c6e609f0d1cccd3f1564c6d24b35e32f1d0ce9..9273bf5fda4244d907b482fbb244e44ed1cb6613 100644
--- a/demo/stderr.py
+++ b/demo/stderr.py
@@ -39,13 +39,13 @@ while x.loop():
     elif x.timeout():
         pass
     elif x.eof(user):
-        print "EOF on user"
+        print("EOF on user")
         break
     elif x.eof(sh_err):
-        print "EOF on stderr"
+        print("EOF on stderr")
         break
     elif x.eof(sh):
-        print "EOF on stdout"
+        print("EOF on stdout")
         break
 
 sh.close()
diff --git a/demo/telnet.py b/demo/telnet.py
index f83c7bbb8acbdb67e02277af0d0f8c2795dd623b..e498cca3abbc6a832794815436e78e7c0d214969 100644
--- a/demo/telnet.py
+++ b/demo/telnet.py
@@ -36,7 +36,7 @@ try:
     password = sys.stdin.readline()
 finally:
     os.system("stty echo")
-print
+print()
 
 if len(password) > 0 and password[-1] == "\n":
     password = password[:-1]
@@ -61,14 +61,14 @@ while x.loop():
         t.send("uname -a\n")
         break
     elif x.re(t, "incorrect"):
-        print "Wrong password"
+        print("Wrong password")
         t.close()
         sys.exit(1)
         
 x = pcl_expect.Controller()
 while x.loop():
     if x.re(t, "(.*)\r?\n.*(>|\\$|#)"):
-        print "SYSTEM ID:", t.match.group(1)
+        print("SYSTEM ID:", t.match.group(1))
         t.send("exit\n")
         break
         
diff --git a/pcl_expect/__init__.py b/pcl_expect/__init__.py
index 5bf383960e0f40e722396938ad6416d75373877d..fa2ab54fed80e42501f405cd02c5396347497d12 100644
--- a/pcl_expect/__init__.py
+++ b/pcl_expect/__init__.py
@@ -153,7 +153,7 @@ class Expectable:
 
         try:
             s = os.read(self.fileno(), 8192)
-        except OSError, e:
+        except OSError as e:
             if e.errno == errno.EIO:
                 debug("got EIO from fd %d" % self.fileno())
                 s = ""
@@ -378,7 +378,7 @@ class Controller:
 
         # Doing this compilation again and again could be a problem.
         # I rely on the cache in module re.  I hope it exists...
-        if isinstance(regexp, basestring):
+        if isinstance(regexp, str):
             regexp = re.compile(regexp)
 
         match = regexp.search(exp.buffer())
diff --git a/pcl_expect/remote_exception.py b/pcl_expect/remote_exception.py
index 44a82d989c6520409d9479446ad49e36047bcec5..b558892d7162f222321717a844bf1216d2753435 100644
--- a/pcl_expect/remote_exception.py
+++ b/pcl_expect/remote_exception.py
@@ -57,7 +57,7 @@
 """
 
 import sys
-import cPickle
+import pickle
 import traceback
 
 class Remote(Exception):
@@ -91,12 +91,12 @@ def serialize():
     """
 
     x = Remote()
-    return cPickle.dumps(x, cPickle.HIGHEST_PROTOCOL)
+    return pickle.dumps(x, pickle.HIGHEST_PROTOCOL)
 
 def re_raise(s):
     """Decode a serialized Remote exception, and raise it."""
 
-    raise cPickle.loads(s)
+    raise pickle.loads(s)
 
 # Demo code follows.
 if __name__ == "__main__":
@@ -107,8 +107,8 @@ if __name__ == "__main__":
 
     try:
         re_raise(y)
-    except Remote, z:
-        print "Remote exception follows:"
-        print z.traceback
-        print "The exception was re-generated here:"
-        print ''.join(traceback.format_exception(*sys.exc_info()))
+    except Remote as z:
+        print("Remote exception follows:")
+        print(z.traceback)
+        print("The exception was re-generated here:")
+        print(''.join(traceback.format_exception(*sys.exc_info())))
diff --git a/pcl_expect/spawn.py b/pcl_expect/spawn.py
index a1a431549291668c51aecc099bd539087d4e98a0..e3ebbeccb228f266c1e90e3cdbb23e4f3adb05ad 100644
--- a/pcl_expect/spawn.py
+++ b/pcl_expect/spawn.py
@@ -130,7 +130,7 @@ def _spawn(cmd, inherit_stty, stty_init, use_stderr_pipe):
         settings = f.read()
         f.close()
 
-    if isinstance(cmd, basestring):
+    if isinstance(cmd, str):
         cmd = cmd.split(" ")
 
     # Create a synchronization pipe, so that the parent doesn't
@@ -232,7 +232,7 @@ class Spawn(pcl_expect.Expectable):
         # when the process dies.  Treat this as a normal end-of-file.
         try:
             return pcl_expect.Expectable._read(self)
-        except OSError, err:
+        except OSError as err:
             if err.errno == errno.EIO:
                 return "", True
             raise
diff --git a/setup.py b/setup.py
index 2e3557ad0e4ea56e785cbad460f2bec62ec5ebbc..fe58d160202b6a42207bef0e944c049622700053 100755
--- a/setup.py
+++ b/setup.py
@@ -35,7 +35,7 @@ setup(name="pcl-expect",
       For example, not only can you talk to processes via a pty, but you can
       also talk to a Telnet server, any TCP server, a serial port, et c.
       """,
-      classifiers = filter(None, classifiers.split("\n")),
+      classifiers = [_f for _f in classifiers.split("\n") if _f],
       platforms = ["POSIX"],
       keywords = "expect pcl-expect pty telnet serial pipe tcp popen"
      )