diff --git a/kwant/__init__.py b/kwant/__init__.py
index 442a6ddfbd7fe72c7033bf9b95ce363c3b730bf3..1fddab25426261753a81e358a30ddab009ac3171 100644
--- a/kwant/__init__.py
+++ b/kwant/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2011-2013 Kwant authors.
+# Copyright 2011-2017 Kwant authors.
 #
 # This file is part of Kwant.  It is subject to the license terms in the file
 # LICENSE.rst found in the top-level directory of this distribution and at
@@ -8,6 +8,10 @@
 
 __all__ = []
 
+from . import version
+version.ensure_python()
+__version__ = version.version
+
 import numpy                    # Needed by C. Gohlke's Windows package.
 import warnings
 
@@ -28,8 +32,6 @@ from ._common import KwantDeprecationWarning, UserCodeError
 
 __all__.extend(['KwantDeprecationWarning', 'UserCodeError'])
 
-from ._common import version as __version__
-
 for module in ['system', 'builder', 'lattice', 'solvers', 'digest', 'rmt',
                'operator', 'kpm', 'wraparound', 'continuum']:
     exec('from . import {0}'.format(module))
diff --git a/kwant/_common.py b/kwant/_common.py
index 0836c6cc94ad471d0c754b63c5aa1a377aee3978..d3d6c46acf36e3f8733e33765fd2ce3c7095887a 100644
--- a/kwant/_common.py
+++ b/kwant/_common.py
@@ -6,81 +6,11 @@
 # the file AUTHORS.rst at the top-level directory of this distribution and at
 # http://kwant-project.org/authors.
 
-import subprocess
-import os
 import numpy as np
 import numbers
 import inspect
 
-__all__ = ['version', 'KwantDeprecationWarning', 'UserCodeError']
-
-package_root = os.path.dirname(os.path.realpath(__file__))
-distr_root = os.path.dirname(package_root)
-version_file = '_kwant_version.py'
-
-def get_version_from_git():
-    try:
-        p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
-                             cwd=distr_root,
-                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    except OSError:
-        return
-    if p.wait() != 0:
-        return
-    if not os.path.samefile(p.communicate()[0].decode().rstrip('\n'), distr_root):
-        # The top-level directory of the current Git repository is not the same
-        # as the root directory of the Kwant distribution: do not extract the
-        # version from Git.
-        return
-
-    # git describe --first-parent does not take into account tags from branches
-    # that were merged-in.
-    for opts in [['--first-parent'], []]:
-        try:
-            p = subprocess.Popen(['git', 'describe', '--long'] + opts,
-                                 cwd=distr_root,
-                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        except OSError:
-            return
-        if p.wait() == 0:
-            break
-    else:
-        return
-    description = p.communicate()[0].decode().strip('v').rstrip('\n')
-
-    release, dev, git = description.rsplit('-', 2)
-    version = [release]
-    labels = []
-    if dev != "0":
-        version.append(".dev{}".format(dev))
-        labels.append(git)
-
-    try:
-        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root)
-    except OSError:
-        labels.append('confused') # This should never happen.
-    else:
-        if p.wait() == 1:
-            labels.append('dirty')
-
-    if labels:
-        version.append('+')
-        version.append(".".join(labels))
-
-    return "".join(version)
-
-
-
-# populate the version_info dictionary with values stored in the version file
-version_info = {}
-with open(os.path.join(package_root, version_file), 'r') as f:
-    exec(f.read(), {}, version_info)
-version = version_info['version']
-version_is_from_git = (version == "__use_git__")
-if version_is_from_git:
-    version = get_version_from_git()
-    if not version:
-        version = "unknown"
+__all__ = ['KwantDeprecationWarning', 'UserCodeError']
 
 
 class KwantDeprecationWarning(Warning):
diff --git a/kwant/version.py b/kwant/version.py
new file mode 100644
index 0000000000000000000000000000000000000000..8360166c6abdc3849db1e29cc80e94a0fa2057dc
--- /dev/null
+++ b/kwant/version.py
@@ -0,0 +1,97 @@
+# Copyright 2011-2017 Kwant authors.
+#
+# This file is part of Kwant.  It is subject to the license terms in the file
+# LICENSE.rst found in the top-level directory of this distribution and at
+# http://kwant-project.org/license.  A list of Kwant authors can be found in
+# the file AUTHORS.rst at the top-level directory of this distribution and at
+# http://kwant-project.org/authors.
+
+# This module must also work with Python 2.
+from __future__ import print_function
+
+import sys
+import subprocess
+import os
+
+# No public API
+__all__ = []
+
+package_root = os.path.dirname(os.path.realpath(__file__))
+distr_root = os.path.dirname(package_root)
+version_file = '_kwant_version.py'
+
+
+def ensure_python(required_version=(3, 4)):
+    v = sys.version_info
+    if v[:3] < required_version:
+        error = "This version of Kwant requires Python {} or above.".format(
+            ".".join(str(p) for p in required_version))
+        if v[0] == 2:
+            error += "\nKwant 1.1 is the last version to support Python 2."
+        print(error, file=sys.stderr)
+        sys.exit(1)
+
+
+def get_version_from_git():
+    try:
+        p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
+                             cwd=distr_root,
+                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    except OSError:
+        return
+    if p.wait() != 0:
+        return
+    if not os.path.samefile(p.communicate()[0].decode().rstrip('\n'),
+                            distr_root):
+        # The top-level directory of the current Git repository is not the same
+        # as the root directory of the Kwant distribution: do not extract the
+        # version from Git.
+        return
+
+    # git describe --first-parent does not take into account tags from branches
+    # that were merged-in.
+    for opts in [['--first-parent'], []]:
+        try:
+            p = subprocess.Popen(['git', 'describe', '--long'] + opts,
+                                 cwd=distr_root,
+                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except OSError:
+            return
+        if p.wait() == 0:
+            break
+    else:
+        return
+    description = p.communicate()[0].decode().strip('v').rstrip('\n')
+
+    release, dev, git = description.rsplit('-', 2)
+    version = [release]
+    labels = []
+    if dev != "0":
+        version.append(".dev{}".format(dev))
+        labels.append(git)
+
+    try:
+        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root)
+    except OSError:
+        labels.append('confused') # This should never happen.
+    else:
+        if p.wait() == 1:
+            labels.append('dirty')
+
+    if labels:
+        version.append('+')
+        version.append(".".join(labels))
+
+    return "".join(version)
+
+
+# populate the version_info dictionary with values stored in the version file
+version_info = {}
+with open(os.path.join(package_root, version_file), 'r') as f:
+    exec(f.read(), {}, version_info)
+version = version_info['version']
+version_is_from_git = (version == "__use_git__")
+if version_is_from_git:
+    version = get_version_from_git()
+    if not version:
+        version = "unknown"
diff --git a/setup.py b/setup.py
index 74c299f831913e5fe9246c973e6ee43593055091..c90f2eb489f1d30199cc210aad985849e9a7dba2 100755
--- a/setup.py
+++ b/setup.py
@@ -12,19 +12,6 @@ from __future__ import print_function
 
 import sys
 
-
-def ensure_python(required_version):
-    v = sys.version_info
-    if v[:3] < required_version:
-        error = "This version of Kwant requires Python {} or above.".format(
-            ".".join(str(p) for p in required_version))
-        if v[0] == 2:
-            error += "\nKwant 1.1 is the last version to support Python 2."
-        print(error, file=sys.stderr)
-        sys.exit(1)
-
-ensure_python((3, 4))
-
 import re
 import os
 import glob
@@ -131,18 +118,19 @@ def configure_extensions(exts, aliases=(), build_summary=None):
     return exts
 
 
-def get_version():
+def check_versions():
     global version, version_is_from_git
 
     # Let Kwant itself determine its own version.  We cannot simply import
     # kwant, as it is not built yet.
     _dont_write_bytecode_saved = sys.dont_write_bytecode
     sys.dont_write_bytecode = True
-    _common = imp.load_source('_common', 'kwant/_common.py')
+    version_module = imp.load_source('version', 'kwant/version.py')
     sys.dont_write_bytecode = _dont_write_bytecode_saved
 
-    version = _common.version
-    version_is_from_git = _common.version_is_from_git
+    version_module.ensure_python()
+    version = version_module.version
+    version_is_from_git = version_module.version_is_from_git
 
 
 def init_cython():
@@ -560,6 +548,8 @@ def maybe_cythonize(exts):
 
 
 def main():
+    check_versions()
+
     exts = collections.OrderedDict([
         ('kwant._system',
          dict(sources=['kwant/_system.pyx'],
@@ -606,7 +596,6 @@ def main():
     aliases = [('lapack', 'kwant.linalg.lapack'),
                ('mumps', 'kwant.linalg._mumps')]
 
-    get_version()
     init_cython()
 
     global build_summary