diff --git a/xbob/io/externals.cpp b/xbob/io/externals.cpp
index 3f1e1c585503610f2966399dcb530fb047262cb6..f7abc1d88393019b155f5368e4b0e0b0b3e44532 100644
--- a/xbob/io/externals.cpp
+++ b/xbob/io/externals.cpp
@@ -941,9 +941,27 @@ PyDoc_STRVAR(module_docstr,
 "Information about software used to compile the C++ Bob API"
 );
 
+#if PY_VERSION_HEX >= 0x03000000
+static PyModuleDef module_definition = {
+  PyModuleDef_HEAD_INIT,
+  XBOB_EXT_MODULE_NAME,
+  module_docstr,
+  -1,
+  module_methods, 
+  0, 0, 0, 0
+};
+#endif
+
 PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
 
-  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, module_methods, module_docstr);
+# if PY_VERSION_HEX >= 0x03000000
+  PyObject* m = PyModule_Create(&module_definition);
+  if (!m) return 0;
+# else
+  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, 
+      module_methods, module_docstr);
+  if (!m) return;
+# endif
 
   /* register some constants */
   PyModule_AddIntConstant(m, "__api_version__", XBOB_IO_API_VERSION);
@@ -953,4 +971,8 @@ PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
   /* imports the NumPy C-API */
   import_array();
 
+# if PY_VERSION_HEX >= 0x03000000
+  return m;
+# endif
+
 }
diff --git a/xbob/io/file.cpp b/xbob/io/file.cpp
index 8edb42dc4c6478f31c236196cfaf98fe8ba5f61e..d7c4fe4e002768d84c8437ba498fd1c3d0911e36 100644
--- a/xbob/io/file.cpp
+++ b/xbob/io/file.cpp
@@ -58,7 +58,7 @@ static PyObject* PyBobIoFile_New(PyTypeObject* type, PyObject*, PyObject*) {
 static void PyBobIoFile_Delete (PyBobIoFileObject* o) {
 
   o->f.reset();
-  o->ob_type->tp_free((PyObject*)o);
+  Py_TYPE(o)->tp_free((PyObject*)o);
 
 }
 
@@ -107,8 +107,8 @@ static PyObject* PyBobIoFile_Repr(PyBobIoFileObject* self) {
 # else
   PyString_FromFormat
 # endif
-  ("%s(filename='%s', codec='%s')", s_file_str, self->f->filename().c_str(),
-   self->f->name().c_str());
+  ("%s(filename='%s', codec='%s')", Py_TYPE(self)->tp_name, 
+   self->f->filename().c_str(), self->f->name().c_str());
 }
 
 static PyObject* PyBobIoFile_Filename(PyBobIoFileObject* self) {
@@ -241,8 +241,8 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) {
 static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* slice) {
 
   Py_ssize_t start, stop, step, slicelength;
-  if (PySlice_GetIndicesEx(slice, self->f->size(),
-        &start, &stop, &step, &slicelength) < 0) return 0;
+  if (PySlice_GetIndicesEx(reinterpret_cast<PyObject*>(slice),
+        self->f->size(), &start, &stop, &step, &slicelength) < 0) return 0;
 
   //creates the return array
   const bob::core::array::typeinfo& info = self->f->type();
@@ -310,7 +310,7 @@ static PyObject* PyBobIoFile_GetItem (PyBobIoFileObject* self, PyObject* item) {
    }
    else {
      PyErr_Format(PyExc_TypeError, "File indices must be integers, not %s",
-         item->ob_type->tp_name);
+         Py_TYPE(item)->tp_name);
      return 0;
    }
 }
@@ -621,9 +621,12 @@ static PyObject* PyBobIoFileIterator_Next (PyBobIoFileIteratorObject* self) {
   return PyBobIoFile_GetIndex(self->pyfile, self->curpos++);
 }
 
+#if PY_VERSION_HEX >= 0x03000000
+#  define Py_TPFLAGS_HAVE_ITER 0
+#endif
+
 PyTypeObject PyBobIoFileIterator_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /* ob_size */
+    PyVarObject_HEAD_INIT(0, 0)
     s_fileiterator_str,                         /* tp_name */
     sizeof(PyBobIoFileIteratorObject),          /* tp_basicsize */
     0,                                          /* tp_itemsize */
@@ -662,8 +665,7 @@ static PyObject* PyBobIoFile_Iter (PyBobIoFileObject* self) {
 }
 
 PyTypeObject PyBobIoFile_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /*ob_size*/
+    PyVarObject_HEAD_INIT(0, 0)
     s_file_str,                                 /*tp_name*/
     sizeof(PyBobIoFileObject),                  /*tp_basicsize*/
     0,                                          /*tp_itemsize*/
diff --git a/xbob/io/hdf5.cpp b/xbob/io/hdf5.cpp
index 2ff54113af822fdacf0cf6ccfd5e3a1341a44260..17cf508ea80d7b4d02c5513e5baba89528a0652f 100644
--- a/xbob/io/hdf5.cpp
+++ b/xbob/io/hdf5.cpp
@@ -70,7 +70,7 @@ static PyObject* PyBobIoHDF5File_New(PyTypeObject* type, PyObject*, PyObject*) {
 static void PyBobIoHDF5File_Delete (PyBobIoHDF5FileObject* o) {
 
   o->f.reset();
-  o->ob_type->tp_free((PyObject*)o);
+  Py_TYPE(o)->tp_free((PyObject*)o);
 
 }
 
@@ -114,7 +114,7 @@ static PyObject* PyBobIoHDF5File_Repr(PyBobIoHDF5FileObject* self) {
 # else
   PyString_FromFormat
 # endif
-  ("%s(filename='%s')", s_hdf5file_str, self->f->filename().c_str());
+  ("%s(filename='%s')", Py_TYPE(self)->tp_name, self->f->filename().c_str());
 }
 
 static PyObject* PyBobIoHDF5File_ChangeDirectory(PyBobIoHDF5FileObject* self, PyObject *args, PyObject* kwds) {
@@ -1063,7 +1063,7 @@ static PyObject* PyBobIoHDF5File_Replace(PyBobIoHDF5FileObject* self, PyObject*
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
   if (is_array < 0) { ///< error condition, signal
-    PyErr_Format(PyExc_TypeError, "error replacing position %" PY_FORMAT_SIZE_T "d of dataset `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", pos, path, self->f->filename().c_str(), data->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "error replacing position %" PY_FORMAT_SIZE_T "d of dataset `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", pos, path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
   }
 
@@ -1197,7 +1197,7 @@ static int PyBobIoHDF5File_InnerAppend(PyBobIoHDF5FileObject* self, const char*
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
   if (is_array < 0) { ///< error condition, signal
-    PyErr_Format(PyExc_TypeError, "error appending to object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), data->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "error appending to object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
   }
 
@@ -1389,7 +1389,7 @@ static PyObject* PyBobIoHDF5File_Set(PyBobIoHDF5FileObject* self, PyObject* args
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
   if (is_array < 0) { ///< error condition, signal
-    PyErr_Format(PyExc_TypeError, "error setting object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), data->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "error setting object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
   }
 
@@ -1923,7 +1923,7 @@ static PyObject* PyBobIoHDF5File_SetAttribute(PyBobIoHDF5FileObject* self, PyObj
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(value, type, &converted);
   if (is_array < 0) { ///< error condition, signal
-    PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name, path, self->f->filename().c_str(), value->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name, path, self->f->filename().c_str(), Py_TYPE(value)->tp_name);
     return 0;
   }
 
@@ -1993,7 +1993,7 @@ static PyObject* PyBobIoHDF5File_SetAttributes(PyBobIoHDF5FileObject* self, PyOb
 
     int is_array = PyBobIoHDF5File_GetObjectType(value, type, &converted);
     if (is_array < 0) { ///< error condition, signal
-      PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name, path, self->f->filename().c_str(), value->ob_type->tp_name);
+      PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name, path, self->f->filename().c_str(), Py_TYPE(value)->tp_name);
       return 0;
     }
 
@@ -2394,8 +2394,7 @@ static PyGetSetDef PyBobIoHDF5File_getseters[] = {
 };
 
 PyTypeObject PyBobIoHDF5File_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /*ob_size*/
+    PyVarObject_HEAD_INIT(0, 0)
     s_hdf5file_str,                             /*tp_name*/
     sizeof(PyBobIoHDF5FileObject),              /*tp_basicsize*/
     0,                                          /*tp_itemsize*/
diff --git a/xbob/io/main.cpp b/xbob/io/main.cpp
index db8f872873bc4461c4c827516fd7a8d56e4fee91..c30def1141549123aa02113a6f4f70aea51f1206 100644
--- a/xbob/io/main.cpp
+++ b/xbob/io/main.cpp
@@ -21,30 +21,71 @@ PyDoc_STRVAR(module_docstr, "bob::io classes and methods");
 
 int PyXbobIo_APIVersion = XBOB_IO_API_VERSION;
 
+#if PY_VERSION_HEX >= 0x03000000
+static PyModuleDef module_definition = {
+  PyModuleDef_HEAD_INIT,
+  XBOB_EXT_MODULE_NAME,
+  module_docstr,
+  -1,
+  module_methods, 
+  0, 0, 0, 0
+};
+#endif
+
 PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
 
   PyBobIoFile_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoFile_Type) < 0) return;
+  if (PyType_Ready(&PyBobIoFile_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
 
   PyBobIoFileIterator_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoFileIterator_Type) < 0) return;
+  if (PyType_Ready(&PyBobIoFileIterator_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
 
 #if WITH_FFMPEG
   PyBobIoVideoReader_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoReader_Type) < 0) return;
+  if (PyType_Ready(&PyBobIoVideoReader_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
 
   PyBobIoVideoReaderIterator_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoReaderIterator_Type) < 0) return;
+  if (PyType_Ready(&PyBobIoVideoReaderIterator_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
 
   PyBobIoVideoWriter_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoWriter_Type) < 0) return;
+  if (PyType_Ready(&PyBobIoVideoWriter_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
 #endif /* WITH_FFMPEG */
 
   PyBobIoHDF5File_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoHDF5File_Type) < 0) return;
-
-  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME,
+  if (PyType_Ready(&PyBobIoHDF5File_Type) < 0) return
+# if PY_VERSION_HEX >= 0x03000000
+    0
+# endif
+    ;
+
+# if PY_VERSION_HEX >= 0x03000000
+  PyObject* m = PyModule_Create(&module_definition);
+  if (!m) return 0;
+# else
+  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, 
       module_methods, module_docstr);
+  if (!m) return;
+# endif
 
   /* register some constants */
   PyModule_AddIntConstant(m, "__api_version__", XBOB_IO_API_VERSION);
@@ -140,4 +181,8 @@ PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
   /* imports xbob.blitz C-API */
   import_xbob_blitz();
 
+# if PY_VERSION_HEX >= 0x03000000
+  return m;
+# endif
+
 }
diff --git a/xbob/io/videoreader.cpp b/xbob/io/videoreader.cpp
index ed5b8152d501e6db9d981ae5d0da293e2e0d6b28..439bd79eace6d73339b08fb24dd1c351fcb9b2f4 100644
--- a/xbob/io/videoreader.cpp
+++ b/xbob/io/videoreader.cpp
@@ -66,7 +66,7 @@ static PyObject* PyBobIoVideoReader_New(PyTypeObject* type, PyObject*, PyObject*
 static void PyBobIoVideoReader_Delete (PyBobIoVideoReaderObject* o) {
 
   o->v.reset();
-  o->ob_type->tp_free((PyObject*)o);
+  Py_TYPE(o)->tp_free((PyObject*)o);
 
 }
 
@@ -307,7 +307,7 @@ static PyObject* PyBobIoVideoReader_Repr(PyBobIoVideoReaderObject* self) {
 # else
   PyString_FromFormat
 # endif
-  ("%s(filename='%s')", s_videoreader_str, self->v->filename().c_str());
+  ("%s(filename='%s')", Py_TYPE(self)->tp_name, self->v->filename().c_str());
 }
 
 /**
@@ -447,8 +447,8 @@ static PyObject* PyBobIoVideoReader_GetIndex (PyBobIoVideoReaderObject* self, Py
 static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, PySliceObject* slice) {
 
   Py_ssize_t start, stop, step, slicelength;
-  if (PySlice_GetIndicesEx(slice, self->v->numberOfFrames(),
-        &start, &stop, &step, &slicelength) < 0) return 0;
+  if (PySlice_GetIndicesEx(reinterpret_cast<PyObject*>(slice), 
+        self->v->numberOfFrames(), &start, &stop, &step, &slicelength) < 0) return 0;
 
   //creates the return array
   const bob::core::array::typeinfo& info = self->v->frame_type();
@@ -528,8 +528,8 @@ static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, PyO
      return PyBobIoVideoReader_GetSlice(self, (PySliceObject*)item);
    }
    else {
-     PyErr_Format(PyExc_TypeError, "VideoReader indices must be integers, not %.200s",
-         item->ob_type->tp_name);
+     PyErr_Format(PyExc_TypeError, "VideoReader indices must be integers, not `%s'",
+         Py_TYPE(item)->tp_name);
      return 0;
    }
 }
@@ -602,9 +602,12 @@ static PyObject* PyBobIoVideoReaderIterator_Next (PyBobIoVideoReaderIteratorObje
 
 }
 
+#if PY_VERSION_HEX >= 0x03000000
+#  define Py_TPFLAGS_HAVE_ITER 0
+#endif
+
 PyTypeObject PyBobIoVideoReaderIterator_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /* ob_size */
+    PyVarObject_HEAD_INIT(0, 0)
     s_videoreaderiterator_str,                  /* tp_name */
     sizeof(PyBobIoVideoReaderIteratorObject),   /* tp_basicsize */
     0,                                          /* tp_itemsize */
@@ -646,8 +649,7 @@ static PyObject* PyBobIoVideoReader_Iter (PyBobIoVideoReaderObject* self) {
 }
 
 PyTypeObject PyBobIoVideoReader_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /*ob_size*/
+    PyVarObject_HEAD_INIT(0, 0)
     s_videoreader_str,                          /*tp_name*/
     sizeof(PyBobIoVideoReaderObject),           /*tp_basicsize*/
     0,                                          /*tp_itemsize*/
diff --git a/xbob/io/videowriter.cpp b/xbob/io/videowriter.cpp
index 8ee51fa8e47811a1cdf7257cd5b009bca8609881..5d5c5f3e672e84d5f34b57f6c8d77b6c7039d51e 100644
--- a/xbob/io/videowriter.cpp
+++ b/xbob/io/videowriter.cpp
@@ -85,7 +85,7 @@ static PyObject* PyBobIoVideoWriter_New(PyTypeObject* type, PyObject*, PyObject*
 static void PyBobIoVideoWriter_Delete (PyBobIoVideoWriterObject* o) {
 
   o->v.reset();
-  o->ob_type->tp_free((PyObject*)o);
+  Py_TYPE(o)->tp_free((PyObject*)o);
 
 }
 
@@ -397,7 +397,7 @@ static PyObject* PyBobIoVideoWriter_Repr(PyBobIoVideoWriterObject* self) {
 # else
   PyString_FromFormat
 # endif
-  ("%s(filename='%s', height=%" PY_FORMAT_SIZE_T "d, width=%" PY_FORMAT_SIZE_T "d, framerate=%g, bitrate=%g, gop=%" PY_FORMAT_SIZE_T "d, codec='%s', format='%s')", s_videowriter_str, self->v->filename().c_str(), self->v->height(), self->v->width(), self->v->frameRate(), self->v->bitRate(), self->v->gop(), self->v->codecName().c_str(), self->v->formatName().c_str());
+  ("%s(filename='%s', height=%" PY_FORMAT_SIZE_T "d, width=%" PY_FORMAT_SIZE_T "d, framerate=%g, bitrate=%g, gop=%" PY_FORMAT_SIZE_T "d, codec='%s', format='%s')", Py_TYPE(self)->tp_name, self->v->filename().c_str(), self->v->height(), self->v->width(), self->v->frameRate(), self->v->bitRate(), self->v->gop(), self->v->codecName().c_str(), self->v->formatName().c_str());
 }
 
 static PyObject* PyBobIoVideoWriter_Append(PyBobIoVideoWriterObject* self, PyObject *args, PyObject* kwds) {
@@ -501,8 +501,7 @@ static PyMappingMethods PyBobIoVideoWriter_Mapping = {
 };
 
 PyTypeObject PyBobIoVideoWriter_Type = {
-    PyObject_HEAD_INIT(0)
-    0,                                          /*ob_size*/
+    PyVarObject_HEAD_INIT(0, 0)
     s_videowriter_str,                          /*tp_name*/
     sizeof(PyBobIoVideoWriterObject),           /*tp_basicsize*/
     0,                                          /*tp_itemsize*/