diff --git a/src/mio.py b/src/mio.py
index b60802f94c27073641aa694a15890d2d3c26e8e8..d6d07782017e33db821d31ffc9fa8f28f6330f16 100755
--- a/src/mio.py
+++ b/src/mio.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+from __future__ import print_function
 import mio.filecache
 import mio.installer
 import mio.log
@@ -45,8 +46,8 @@ def parse(filename, repository):
         try:
             parse_with_path(p, filename, repository)
             return
-        except IOError, e:
-            print e
+        except IOError as e:
+            print(e)
             raise
             pass
     raise Exception("Could not parse %s" % filename)
@@ -62,15 +63,15 @@ class FindAndParse:
                 parse_with_path(path, filename, builder) 
                 self.tried.add((path,filename))
                 return True
-            except IOError, e:
+            except IOError as e:
                 self.tried.add((path,filename))
                 pass
-            except ValueError, e:
+            except ValueError as e:
                 pass
-            except DuplicateGroupException, e:
-                print e
+            except DuplicateGroupException as e:
+                print(e)
                 traceback.print_exc()
-                print "Failed to locate: %s" % target
+                print("Failed to locate: %s" % target)
                 sys.exit(1)
                 pass
             pass
@@ -101,7 +102,7 @@ class FindAndParse:
                             break
                         pass
                     pass
-                except IOError, e:
+                except IOError as e:
                     continue
                 pass
             else:
@@ -118,7 +119,7 @@ class FindAndParse:
             builder.add(tmp1._group_)
             pass
         else:
-            print "Failed to locate: %s" % target
+            print("Failed to locate: %s" % target)
 
 if __name__ == '__main__':
     locale.setlocale(locale.LC_TIME, 'C')
@@ -202,17 +203,17 @@ if __name__ == '__main__':
             parse(url, rules)
 
         error = {}
-        print "Reachable targets:"
+        print("Reachable targets:")
         for g in rules.get_all(error):
             if not options.dump:
-                print "  ",g.name[0]
+                print("  ",g.name[0])
             else:
-                print g._xml(indent=1)
+                print(g._xml(indent=1))
 
         for e in error:
-            print "Unresolved group: '%s'" % e
+            print("Unresolved group: '%s'" % e)
             for r in error[e]:
-                print "  from: '%s' in %s:%s" % (r.name[0], r._url, r._line)
+                print("  from: '%s' in %s:%s" % (r.name[0], r._url, r._line))
 
     if options.list_rpms:
         installer = mio.installer.Installer(rules)
@@ -222,7 +223,7 @@ if __name__ == '__main__':
 
         log(NORMAL, "# List rpms for %s" % options.list_rpms)
         for r in installer.list_rpms():
-            print r
+            print(r)
             pass
         pass
     
@@ -261,14 +262,14 @@ if __name__ == '__main__':
             keys = files.keys()
             keys.sort()
             for k in keys:
-                print k
+                print(k)
             pass
         else:
             for e in error:
-                print "Unresolved group: '%s'" % e
+                print("Unresolved group: '%s'" % e)
                 for r in error[e]:
-                    print "  from: '%s' in %s:%s" % (r.name[0],
-                                                     r._url, r._line)
+                    print("  from: '%s' in %s:%s" % (r.name[0],
+                                                     r._url, r._line))
                     pass
                 pass
             pass
@@ -298,14 +299,14 @@ if __name__ == '__main__':
             keys = rpms.keys()
             keys.sort()
             for k in keys:
-                print k
+                print(k)
             pass
         else:
             for e in error:
-                print "Unresolved group: '%s'" % e
+                print("Unresolved group: '%s'" % e)
                 for r in error[e]:
-                    print "  from: '%s' in %s:%s" % (r.name[0],
-                                                     r._url, r._line)
+                    print("  from: '%s' in %s:%s" % (r.name[0],
+                                                     r._url, r._line))
                     pass
                 pass
             pass
@@ -336,7 +337,7 @@ if __name__ == '__main__':
                 (rpm_result, failed) = installer.install_rpms(
                     options.path, options.exclude_rpm)
                 pass
-            except Exception, e:
+            except Exception as e:
                 log(MUTE, "Failed to install rpm's, rerun with '--noyum'")
                 exit(1)
                 pass
@@ -345,7 +346,7 @@ if __name__ == '__main__':
                                  (options.backup, options.backup_suffix))
 
     if rpm_result:
-        print "Yum failed with %d" % rpm_result
+        print("Yum failed with %d" % rpm_result)
         for r in failed:
-            print "Failed to install %s" % r
+            print("Failed to install %s" % r)
         exit(1)
diff --git a/src/mio/daemon_cage.py b/src/mio/daemon_cage.py
index 491d51004871ed35b224ebeaea40ec072387b71c..8a24ba52fd1c11ed82c33509ea1f181525a6fbf0 100755
--- a/src/mio/daemon_cage.py
+++ b/src/mio/daemon_cage.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+from __future__ import print_function
 import os
 import resource
 import select
@@ -37,7 +38,7 @@ def system(command):
     else:
         # Create another deamon that puts the deamon still lingering
         # from above in a cage that puts all output in syslog
-        print "Caging '%s'" % command
+        print("Caging '%s'" % command)
         pid = os.fork()
         if (pid != 0):
             # At this point, let the parent process continue
diff --git a/src/mio/exception.py b/src/mio/exception.py
index 52b32f3d50dce0aac75071a16f17fb345987078e..989c1eca39b059c96709404d7d03d8ffe0cdb74b 100755
--- a/src/mio/exception.py
+++ b/src/mio/exception.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import traceback
 import sys
 import urllib2
@@ -6,7 +7,7 @@ def declaration(decl):
     try:
         result = "[%s:%s] " % (decl._url, decl._line)
         return result
-    except Exception, e:
+    except Exception as e:
         return ""
 
 class MioException(Exception):
@@ -116,7 +117,7 @@ def Report(err, decl, action=None):
     traceback.print_exc()
     message = "%s:%s" % (decl._url, decl._line)
     if action:
-        message += " (%s)" % action.im_func.func_name
+        message += " (%s)" % action.__func__.__name__
     message += "  %s: %s" % (err.__class__.__name__, err)
-    print message
+    print(message)
     sys.exit(1)
diff --git a/src/mio/filecache.py b/src/mio/filecache.py
index 4706f80712b3aeddfc25c118cfd6d5fc2338fcde..cb89186dc2af60edd830d11b3076c6061ba59f45 100755
--- a/src/mio/filecache.py
+++ b/src/mio/filecache.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import atexit
 import calendar
 import os
@@ -95,7 +96,7 @@ class Unalias:
             result.append(urlparse.urlunsplit(('file', '', u.path, '', '')))
             pass
         else:
-            print u
+            print(u)
             pass
         return result
  
@@ -116,7 +117,7 @@ class Mirror:
     def urlopen(self, path):
         try:
             return self.mirror.urlopen(str(path))
-        except urlgrabber.grabber.URLGrabError, e:
+        except urlgrabber.grabber.URLGrabError as e:
             raise IOError("Failed to get '%s' (%s)" % (path, e))
             raise
             
@@ -166,12 +167,12 @@ def cleanup():
 def createfile():
     f = open(tempfile.mktemp(), 'w')
     temp.append(f.name)
-    os.chmod(f.name, 0700)
+    os.chmod(f.name, 0o700)
     return f
 
 def createdir():
     d = tempfile.mktemp()
-    os.mkdir(d, 0700)
+    os.mkdir(d, 0o700)
     temp.append(d)
     return d
     
@@ -202,7 +203,7 @@ def loadfile(path, *name):
 def loadscript(path, *name):
     result = loadfile(path, *name)
     if result.filename in temp:
-        os.chmod(result.filename, 0700)
+        os.chmod(result.filename, 0o700)
     return result
 
 def localpath(prefix, *path):
diff --git a/src/mio/installer.py b/src/mio/installer.py
index cea28c4c0b42d151a1635b9db8a3df15ca5203f3..678287bf14dcffac0dfa157d61d00c453ee00e76 100755
--- a/src/mio/installer.py
+++ b/src/mio/installer.py
@@ -1,9 +1,10 @@
+from __future__ import print_function
 import fnmatch
 import sys
 try:
     import mio.rpmDB
-except ImportError, e:
-    print>>sys.stdout, 'No rpm support [neither python-dnf or yum installed]'
+except ImportError as e:
+    print('No rpm support [neither python-dnf or yum installed]', file=sys.stdout)
     pass
 import mio.util
 import mio.yum
@@ -116,14 +117,14 @@ class Installer:
                 try:
                     old_group.assert_identical(group)
                     result = old_group
-                except MioException, e:
-                    print e
-                    print "Old expansion order was:"
+                except MioException as e:
+                    print(e)
+                    print("Old expansion order was:")
                     for t in old_chain:
-                        print "  ", declaration(t.decl), t.decl.name[0]
-                    print "New expansion order is:"
+                        print("  ", declaration(t.decl), t.decl.name[0])
+                    print("New expansion order is:")
                     for t in chain:
-                        print "  ", declaration(t.decl), t.decl.name[0]
+                        print("  ", declaration(t.decl), t.decl.name[0])
                     sys.exit(1)
             else:
                 result = group
@@ -200,7 +201,7 @@ class Installer:
             return not any(map(lambda x: fnmatch.fnmatch(name, x), exclude))
         rpm = filter(not_excluded, rpm)
         #rpm.sort()
-        print rpm
+        print(rpm)
         result = mio.yum.run(path + self.rpmdir, rpm, exclude)
         version_db = mio.rpmDB.VersionDB()
         for r in self.rpm:
diff --git a/src/mio/log.py b/src/mio/log.py
index ee95adef8c62dcebe81de8fd01d25aa397c8690d..4ec8c19f7de3fbd53bafe626bec6474faf8c0fe3 100755
--- a/src/mio/log.py
+++ b/src/mio/log.py
@@ -25,6 +25,6 @@ def declaration(node):
         if verbosity > NORMAL:
             result = "[%s:%s]" % (node.decl._url, node.decl._line)
             return result
-    except Exception,e :
+    except Exception as e :
         pass
     return ""
diff --git a/src/mio/node.py b/src/mio/node.py
index 737ef8b663dceea8204d316b869001312e19008c..eaacc59e4c7b0e31d000c8d1bde4af9d64d8401c 100755
--- a/src/mio/node.py
+++ b/src/mio/node.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import mio.daemon_cage
 import mio.exception
 import mio.filecache
@@ -57,7 +58,7 @@ class target_node:
                 pass
             except SystemExit:
                 raise
-            except Exception, e:
+            except Exception as e:
                 mio.exception.Report(e, self.decl)
             log(DEBUG, "[%s].trigged %s -> %s" % (self.name, 
                                                 run_pre, self.is_trigged))
@@ -216,7 +217,7 @@ class dir_node(target_node):
                 result = True
                 self.action.append(self.chown)
                 pass
-            if self.mode != (tstat.st_mode & 07777):
+            if self.mode != (tstat.st_mode & 0o7777):
                 result = True
                 self.action.append(self.chmod)
                 pass
@@ -227,17 +228,17 @@ class dir_node(target_node):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
+                    (a.__func__.__name__, self.target))
                 a()
-            except Exception, e:
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
 
     def do_test(self, prefix):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
-            except Exception, e:
+                    (a.__func__.__name__, self.target))
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
 
     def mkdir(self):
@@ -340,7 +341,7 @@ class file_node(target_node):
                 result = True
                 self.action.append(self.chown)
     
-            if self.mode != (tstat.st_mode & 07777):
+            if self.mode != (tstat.st_mode & 0o7777):
                 result = True
                 self.action.append(self.chmod)
     
@@ -352,17 +353,17 @@ class file_node(target_node):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
+                    (a.__func__.__name__, self.target))
                 a(backup)
-            except Exception, e:
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
         
     def do_test(self, prefix):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
-            except Exception, e:
+                    (a.__func__.__name__, self.target))
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
 
     def unlink(self, backup):
@@ -375,7 +376,7 @@ class file_node(target_node):
             backup_name = "%s/%s" % (backup[0], self.decl.name[0])
             if backup[1]:
                 backup_name += backup[1]
-            print "DO backup %s -> %s" % (self.target, backup_name)
+            print("DO backup %s -> %s" % (self.target, backup_name))
             dir = os.path.dirname(backup_name)
             if not os.path.isdir(dir):
                 dirmode = mio.util.dirmode(self.decl._parent)
@@ -488,17 +489,17 @@ class symlink_node(target_node):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
+                    (a.__func__.__name__, self.target))
                 a()
-            except Exception, e:
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
 
     def do_test(self, prefix):
         for a in self.action:
             try:
                 log(NORMAL, declaration(self), "%s '%s'" %
-                    (a.im_func.__name__, self.target))
-            except Exception, e:
+                    (a.__func__.__name__, self.target))
+            except Exception as e:
                 mio.exception.Report(e, self.decl, a)
 
     def unlink(self):
@@ -515,7 +516,7 @@ class symlink_node(target_node):
         # Change owner and group
         try:
             os.lchown(self.target, int(self.uid), int(self.gid))
-        except AttributeError, e:
+        except AttributeError as e:
             log(SILENT, declaration(self), "Warning: no lchown")
             
 class command_node:
diff --git a/src/mio/parser.py b/src/mio/parser.py
index 2fbd4fdd48c68ec21ab63f41e473521310e8a221..8e0f823af97b3240d7dc7b7a8626a29b52cace4c 100755
--- a/src/mio/parser.py
+++ b/src/mio/parser.py
@@ -351,7 +351,7 @@ class Node:
             raise AttributeError(attr)
         elif attr.startswith("_") and attr.endswith("_"):
             return ChildAccessor(self, [attr[1:-1]])
-        elif self.__dict__.has_key(attr):
+        elif attr in self.__dict__:
             return self.__dict__[attr]
         elif attr.startswith("_"):
             if self._parent:
diff --git a/src/mio/repository.py b/src/mio/repository.py
index 9339ea23f528b16c74e4a7a8135f4a519fad2861..c1d5c23eb701e27aeffd5137b73d95f3fd890252 100755
--- a/src/mio/repository.py
+++ b/src/mio/repository.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import mio.filecache
 import mio.path
 import os
@@ -15,7 +16,7 @@ class Repository:
     def add(self, group, join=None):
         for g in group:
             name = g.name[0]
-            if self.group.has_key(name):
+            if name in self.group:
                 og = self.group[name]
                 if join:
                     g = join(og, g)
@@ -32,14 +33,14 @@ class Repository:
         name = target.name[0]
         if self.filter(name):
             return None
-        if not self.group.has_key(name):
+        if name not in self.group:
             # Try to locate target (look in target and default path)
             self.parser(name, self, target._url)
 
             try:
                 pass
-            except Exception, e:
-                print e
+            except Exception as e:
+                print(e)
                 raise Exception("%s\n" % e.__str__() +
                                 "  while locating '%s' at\n" % name +
                                 "    %s:%d\n" % (target._url, target._line))
@@ -67,10 +68,10 @@ class Repository:
                 try:
                     d = g._dependency_
                     result.extend(self.expand(d, error, done))
-                except Exception, e:
+                except Exception as e:
                     if error != None:
                         key = e.args[0]
-                        if not error.has_key(key):
+                        if key not in error:
                             error[key] = []
                         error[key].append(g)
                     else:
diff --git a/src/mio/rpmDB.py b/src/mio/rpmDB.py
index 96e44621dff45feb8b77612a52743534aa85eaa2..07ef123fcd730e56d4d9f84eec8327f7a2ff1d7f 100755
--- a/src/mio/rpmDB.py
+++ b/src/mio/rpmDB.py
@@ -1,7 +1,7 @@
 try:
     import rpmUtils.transaction
     initReadOnlyTransaction = rpmUtils.transaction.initReadOnlyTransaction
-except ImportError, e:
+except ImportError as e:
     # Let's guess we are running dnf
     import dnf.rpm.transaction
     initReadOnlyTransaction = dnf.rpm.transaction.initReadOnlyTransaction
diff --git a/src/mio/transform.py b/src/mio/transform.py
index 03aba20b67654ef6b4d3c89d7bd481e3881835b6..012ef39ef77c380619f6ea62f1172f1d8fc0971a 100755
--- a/src/mio/transform.py
+++ b/src/mio/transform.py
@@ -131,7 +131,7 @@ def mio_rename(tree, decl, key):
         value = decl._attr(key)[0]
         if not value.startswith("/") and not value.startswith("@"):
            decl._set(key, "/%s/%s" % (tree.name[0], value))
-    except Exception,e:
+    except Exception as e:
         pass
     
 def from_mio(tree):
diff --git a/src/mio/urlgrabber_compat.py b/src/mio/urlgrabber_compat.py
index b7ba67f23b3419d5e28137216c3f98062fc37fe4..b48ac394dff9e42f96c228f3fc15df4bf822f40f 100755
--- a/src/mio/urlgrabber_compat.py
+++ b/src/mio/urlgrabber_compat.py
@@ -42,7 +42,7 @@ class Compat:
                 url = "%s/%s" % (u, path)
                 try:
                     return CurlWrapper(urllib2.urlopen(url))
-                except IOError, e:
+                except IOError as e:
                     pass
             raise IOError("Failed to get '%s' (%s)" % (path, e))
             
diff --git a/src/mio/util.py b/src/mio/util.py
index b8d8e60deaf6d82ed044cd28f9dc1f27eecd3087..3e691d2349f0cddf3eb54cb6986c4d538aeb9146 100755
--- a/src/mio/util.py
+++ b/src/mio/util.py
@@ -7,21 +7,21 @@ from mio.log import log, NORMAL, VERBOSE
 def mode_mask(s):
     result = 0
     for c in s:
-        if   c == 'u': result |= 04700
-        elif c == 'g': result |= 02070
-        elif c == 'o': result |= 01007
-        elif c == 'a': result |= 07777
+        if   c == 'u': result |= 0o4700
+        elif c == 'g': result |= 0o2070
+        elif c == 'o': result |= 0o1007
+        elif c == 'a': result |= 0o7777
         else: raise Exception("Illegal mode group %c" % c)
     return result
 
 def mode_bits(s):
     result = 0
     for c in s:
-        if   c == 'r': result |= 00444
-        elif c == 'w': result |= 00222
-        elif c == 'x': result |= 00111
-        elif c == 's': result |= 06000
-        elif c == 't': result |= 01000
+        if   c == 'r': result |= 0o0444
+        elif c == 'w': result |= 0o0222
+        elif c == 'x': result |= 0o0111
+        elif c == 's': result |= 0o6000
+        elif c == 't': result |= 0o1000
         else: raise Exception("Illegal mode bits %c" % c)
     return result
 
@@ -54,13 +54,13 @@ def mode_combine(mode):
 
 def filemode(file):
     mode = file.mode[0::1]
-    mode.append(0600)
+    mode.append(0o600)
     return mode_combine(mode)
 
 def dirmode(dir):
     mode = [ dir.mode[0] ]
     mode.extend(dir.dirmode[1::1])
-    mode.append(0700)
+    mode.append(0o700)
     return mode_combine(mode)
 
 def uid(owner):
diff --git a/src/mio/yum.py b/src/mio/yum.py
index d02dcc4c91b404b3ef733b3c83cc6055de4a6a6d..e0874678f2f6ffbcc7d4a8885788691a33b0d56d 100755
--- a/src/mio/yum.py
+++ b/src/mio/yum.py
@@ -50,7 +50,7 @@ def yumdir(path):
 
 def conf(path):
     if not os.path.isdir("/var/cache/mio"):
-        os.makedirs("/var/cache/mio", 0755)
+        os.makedirs("/var/cache/mio", 0o755)
     result = [ "[main]",
                "cachedir=/var/cache/mio",
                "logfile=/var/log/yum.log",