diff --git a/Modules/Core/Common/include/otbLogger.h b/Modules/Core/Common/include/otbLogger.h
index 4dd6825bd146d10a2fc6a37464db8d3e290e2fe2..6ae206fe2611038834f5721c01c67126420afdc2 100644
--- a/Modules/Core/Common/include/otbLogger.h
+++ b/Modules/Core/Common/include/otbLogger.h
@@ -56,6 +56,8 @@ public:
    */
   static Logger * Instance();
 
+  void ResetOutputs();
+
   static Pointer New();
   itkCreateAnotherMacro( Logger )
   itkCloneMacro( Logger )
diff --git a/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h
index 9cbf761b4c12b5fec6f9309ee6ab38ddfe5cf0f8..7abc307908b0ea856f380208666e61c38402135e 100644
--- a/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h
+++ b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.h
@@ -25,6 +25,7 @@
 #include <iosfwd>
 
 #include "otbFilterWatcherBase.h"
+#include "otbStandardOutputPrintCallback.h"
 
 namespace otb
 {
@@ -46,15 +47,16 @@ namespace otb
  *  StandardOneLineFilterWatcher watcher(thresholdFilter, "Threshold");
  *  \endcode
  *
+ *  \see otb::StandardOutputPrintCallback
  *  \see itk::SimpleFilterWatcher
  *  \see otb::fltkFilterWatcher
  *
  * \ingroup OTBCommon
  */
-class OTBCommon_EXPORT StandardOneLineFilterWatcher : public FilterWatcherBase
+template <class PrintCallbackType = StandardOutputPrintCallback>
+class OTBCommon_EXPORT_TEMPLATE StandardOneLineFilterWatcher : public FilterWatcherBase
 {
 public:
-
   /** Constructor. Takes a ProcessObject to monitor and an optional
    * comment string that is prepended to each event message. */
   StandardOneLineFilterWatcher(itk::ProcessObject* process,
@@ -66,6 +68,9 @@ public:
   /** Default constructor */
   StandardOneLineFilterWatcher();
 
+  /** Destrucotr */
+  ~StandardOneLineFilterWatcher() override = default;
+
   /** Get/Set number of stars */
   void SetStars(int count)
   {
@@ -76,6 +81,12 @@ public:
     return m_StarsCount;
   }
 
+  /** Set the callback class */
+  void SetCallback(PrintCallbackType * callback)
+  {
+    m_Callback = callback;
+  }
+
 protected:
 
   /** Callback method to show the ProgressEvent */
@@ -89,16 +100,31 @@ protected:
 
 private:
 
-  /** Stars coutning */
+  /** Stars counting */
   int m_StarsCount;
 
+  /** Current number of stars, we keep track of this to avoid reprinting the
+   * progress if it hasn't changed */
   int m_CurrentNbStars;
 
-  bool m_CoutIsConsole;
-
+  /** If the output is not interactive (e.g. it is redirected to a file), it
+   * is buffered and only written at the end of the processing */
   std::string m_Buffer;
+  
+  /** The point to the callback used for printing. It is set to the default
+   * callback on construction and can be changed later using the setter.
+   * Delete will not be called on this pointer. */
+  PrintCallbackType * m_Callback;
+  
+  /** A default callback created in the constructor and deleted in the 
+   * destructor. */ 
+  std::shared_ptr<PrintCallbackType> m_DefaultCallback;
 };
 
 } // end namespace otb
 
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbStandardOneLineFilterWatcher.hxx"
+#endif
+
 #endif
diff --git a/Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx
similarity index 65%
rename from Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx
rename to Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx
index f247061da6b4dca59baa48d8b4cf5bb9d7ac3ce8..56489471fc73fa0c5f7246909051c9d04cede370 100644
--- a/Modules/Core/Common/src/otbStandardOneLineFilterWatcher.cxx
+++ b/Modules/Core/Common/include/otbStandardOneLineFilterWatcher.hxx
@@ -19,6 +19,9 @@
  * limitations under the License.
  */
 
+#ifndef otbStandardOneLineFilterWatcher_hxx
+#define otbStandardOneLineFilterWatcher_hxx
+
 #include <iostream>
 #include <sstream>
 
@@ -28,37 +31,43 @@
 
 namespace otb
 {
-
-StandardOneLineFilterWatcher
+template<class PrintCallbackType>
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::StandardOneLineFilterWatcher()
   : m_StarsCount(50),
-    m_CurrentNbStars(-1),
-    m_CoutIsConsole( System::IsInteractive(1) )
+    m_CurrentNbStars(-1)
 {
+  m_DefaultCallback = std::make_shared<PrintCallbackType>() ;
+  m_Callback = m_DefaultCallback.get();
 }
 
-StandardOneLineFilterWatcher
+template<class PrintCallbackType>
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::StandardOneLineFilterWatcher(itk::ProcessObject* process,
                         const char *comment)
   : FilterWatcherBase(process, comment),
     m_StarsCount(50),
-    m_CurrentNbStars(-1),
-    m_CoutIsConsole( System::IsInteractive(1) )
+    m_CurrentNbStars(-1)
 {
+  m_DefaultCallback = std::make_shared<PrintCallbackType>() ;
+  m_Callback = m_DefaultCallback.get();
 }
 
-StandardOneLineFilterWatcher
+template<class PrintCallbackType>
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::StandardOneLineFilterWatcher(itk::ProcessObject* process,
                         const std::string& comment)
   : FilterWatcherBase(process, comment.c_str()),
     m_StarsCount(50),
-    m_CurrentNbStars(-1),
-    m_CoutIsConsole( System::IsInteractive(1) )
+    m_CurrentNbStars(-1)
 {
+  m_DefaultCallback = std::make_shared<PrintCallbackType>() ;
+  m_Callback = m_DefaultCallback.get();
 }
 
+template<class PrintCallbackType>
 void
-StandardOneLineFilterWatcher
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::ShowProgress()
 {
   if (m_Process)
@@ -90,9 +99,10 @@ StandardOneLineFilterWatcher
       oss << m_Comment
           << ": "
           << progressPercent << "% [" << stars << blanks << "]";
-      if (m_CoutIsConsole)
+      if (m_Callback->IsInteractive())
         {
-        std::cout << "\r" << oss.str() << std::flush;
+        m_Callback->Call("\r" + oss.str());
+        m_Callback->Flush();
         }
       else
         {
@@ -104,29 +114,31 @@ StandardOneLineFilterWatcher
     }
 }
 
+template<class PrintCallbackType>
 void
-StandardOneLineFilterWatcher
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::StartFilter()
 {
   m_Stopwatch.Start();
 }
 
+template<class PrintCallbackType>
 void
-StandardOneLineFilterWatcher
+StandardOneLineFilterWatcher<PrintCallbackType>
 ::EndFilter()
 {
   m_Stopwatch.Stop();
 
-  if (m_Process && !m_CoutIsConsole)
+  if (m_Process && !m_Callback->IsInteractive())
     {
-    std::cout << m_Buffer;
+    m_Callback->Call(m_Buffer);
     m_Buffer = std::string("");
     }
 
-  std::cout << " (";
-  m_Stopwatch.GetElapsedHumanReadableTime(std::cout);
-  std::cout << ")"
-            << std::endl;
+  m_Callback->Call(" (" + m_Stopwatch.GetElapsedHumanReadableTime() + ")\n");
+
 }
 
 } // end namespace otb
+
+#endif
diff --git a/Modules/Core/Common/include/otbStandardOutputPrintCallback.h b/Modules/Core/Common/include/otbStandardOutputPrintCallback.h
new file mode 100644
index 0000000000000000000000000000000000000000..2804a98cfc365dc6b1d8b362cebd7d483d73c761
--- /dev/null
+++ b/Modules/Core/Common/include/otbStandardOutputPrintCallback.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbStandardOutputPrintCallback_h
+#define otbStandardOutputPrintCallback_h
+
+#include "otbSystem.h"
+
+namespace otb
+{
+
+/** \class StandardOutputPrintCallback
+ *  \brief Class with printing callback methods using the standard output
+ *
+ *  This class defines the Call method, used to write a string the standard 
+ *  output, the Flush method, used to flush it, and the IsInteractive 
+ *  method used to determine if the output is the console.
+ *  
+ *  \see otb::StandardOneLineFilterWatcher
+ *
+ * \ingroup OTBCommon
+ */
+
+class OTBCommon_EXPORT StandardOutputPrintCallback
+{
+public:
+  /** Constructor */
+  StandardOutputPrintCallback() :m_IsInteractive( System::IsInteractive(1)) {};
+
+  /** Destructor */
+  virtual ~StandardOutputPrintCallback() = default;
+
+  /** Write a string to a buffer */
+  void Call(std::string const& content);
+
+  /** Flush the buffer */
+  void Flush();
+
+  /** Determine if the output is interactive */
+  bool IsInteractive();
+  
+private:
+  /** flag determining if the output is interactive */
+  bool m_IsInteractive;
+};
+
+} // namespace otb
+
+#endif // otbStandardOutputPrintCallback_h
diff --git a/Modules/Core/Common/src/CMakeLists.txt b/Modules/Core/Common/src/CMakeLists.txt
index 91abc0b63f601f34421480cc33e3c12d6320f719..cfbef0afd4cc2b77b1e28995fb414d092ea4c68c 100644
--- a/Modules/Core/Common/src/CMakeLists.txt
+++ b/Modules/Core/Common/src/CMakeLists.txt
@@ -25,12 +25,12 @@ set(OTBCommon_SRC
   otbStandardWriterWatcher.cxx
   otbUtils.cxx
   otbConfigurationManager.cxx
-  otbStandardOneLineFilterWatcher.cxx
   otbWriterWatcherBase.cxx
   otbStopwatch.cxx
   otbStringToHTML.cxx
   otbExtendedFilenameHelper.cxx
   otbLogger.cxx
+  otbStandardOutputPrintCallback.cxx
   )
 
 add_library(OTBCommon ${OTBCommon_SRC})
diff --git a/Modules/Core/Common/src/otbLogger.cxx b/Modules/Core/Common/src/otbLogger.cxx
index e6ba5c2b260eec3bb6ed968d3487ead81718a21d..20685d1651d1bc4d249ab6d862acdc518fcde3e9 100644
--- a/Modules/Core/Common/src/otbLogger.cxx
+++ b/Modules/Core/Common/src/otbLogger.cxx
@@ -49,16 +49,14 @@ Logger * Logger::CreateInstance()
 {
   Logger * logger = new Logger;
 
-  // By default, redirect logs to std::cout
-  itk::StdStreamLogOutput::Pointer defaultOutput = 
-    itk::StdStreamLogOutput::New();
+  // By default redirect logs to std::cout
+  itk::StdStreamLogOutput::Pointer defaultOutput = itk::StdStreamLogOutput::New();
   defaultOutput->SetStream(std::cout);
-  
   logger->AddLogOutput(defaultOutput);
+
   return logger;
 }
 
-
 Logger * Logger::Instance()
 {
   static Logger * logger_singleton = CreateInstance();
@@ -110,6 +108,11 @@ void Logger::LogSetupInformation()
     }
 }
 
+void Logger::ResetOutputs()
+{
+  m_Output = itk::MultipleLogOutput::New();
+}
+
 bool Logger::IsLogSetupInformationDone()
 {
   return m_LogSetupInfoDone;
diff --git a/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx b/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2f41413405d42afcb0d4e372fcfb6f02698148ed
--- /dev/null
+++ b/Modules/Core/Common/src/otbStandardOutputPrintCallback.cxx
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbStandardOutputPrintCallback.h"
+
+namespace otb
+{
+
+void
+StandardOutputPrintCallback
+::Call(std::string const& content)
+{
+  std::cout << content;
+}
+
+void
+StandardOutputPrintCallback
+::Flush()
+{
+  std::cout << std::flush;
+}
+
+bool
+StandardOutputPrintCallback
+::IsInteractive()
+{
+  return m_IsInteractive;
+}
+
+} // namespace otb
diff --git a/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx b/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx
index 5ef1f5eac1bde05480692300f210578910667dcc..dfd9bfcdac45585536754210927515941d98db77 100644
--- a/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx
+++ b/Modules/Core/Common/test/otbStandardOneLineFilterWatcherTest.cxx
@@ -38,7 +38,7 @@ int otbStandardOneLineFilterWatcherTest(int itkNotUsed(argc), char * argv[])
   typedef itk::GradientMagnitudeImageFilter<ImageType, ImageType> FilterType;
   FilterType::Pointer gradient = FilterType::New();
 
-  typedef otb::StandardOneLineFilterWatcher WatcherType;
+  typedef otb::StandardOneLineFilterWatcher<> WatcherType;
   WatcherType watcher1(gradient, "Gradient");
 
   gradient->SetInput(reader->GetOutput());
diff --git a/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx b/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx
index 4452cb65fc3c74273d773f5930c9ba1e5987a3e4..f250c83b96e0b9c32e1dec450357bd58d2369bda 100644
--- a/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx
+++ b/Modules/IO/IOGDAL/test/otbGDALOverviewsBuilder.cxx
@@ -42,7 +42,7 @@ int otbGDALOverviewsBuilder(int itkNotUsed(argc), char* argv[])
   filter->SetResamplingMethod(resamp);
 
   {
-    StandardOneLineFilterWatcher watcher(filter,"Overviews creation");
+    StandardOneLineFilterWatcher<> watcher(filter,"Overviews creation");
     filter->Update();
   }
 
diff --git a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx
index 6470adfd61825a585696cb142d3a7c3252073d0c..24772864ba47f864dd127540874094d7b2f45435 100644
--- a/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx
+++ b/Modules/Visualization/MonteverdiCore/src/mvdVectorImageModel.cxx
@@ -260,7 +260,7 @@ VectorImageModel
 
   try
     {
-    otb::StandardOneLineFilterWatcher watcher(
+    otb::StandardOneLineFilterWatcher<> watcher(
       filter,
       ToStdString( tr( "Overviews creation: " ) )
     );
diff --git a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
index cc28ee8e9cd3b549e15f8a36005e67a06f644538..9e097a67cfafd11f96efc38867ea37e4b643d62b 100644
--- a/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
+++ b/Modules/Wrappers/CommandLine/include/otbWrapperCommandLineLauncher.h
@@ -76,7 +76,7 @@ public:
                  INVALIDNUMBEROFVALUE, DEFAULT} ParamResultType;
 
   /** Filter watcher list type */
-  typedef std::vector<StandardOneLineFilterWatcher *> WatcherListType;
+  typedef std::vector<StandardOneLineFilterWatcher<> *> WatcherListType;
 
   /** Command Member */
   typedef itk::MemberCommand< Self >        AddProcessCommandType;
diff --git a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
index bed8cd21dcbbfd8af0cf2cd0491151a2d7aa5a0e..a68201fa8f497ffdd086e9945cc6d010cb7be03a 100644
--- a/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
+++ b/Modules/Wrappers/CommandLine/src/otbWrapperCommandLineLauncher.cxx
@@ -596,7 +596,7 @@ void CommandLineLauncher::LinkWatchers(itk::Object * itkNotUsed(caller), const i
       {
       const AddProcessToWatchEvent* eventToWatch = dynamic_cast<const AddProcessToWatchEvent*> (&event);
 
-      StandardOneLineFilterWatcher * watch = new StandardOneLineFilterWatcher(eventToWatch->GetProcess(),
+      auto watch = new StandardOneLineFilterWatcher<>(eventToWatch->GetProcess(),
                                                                               eventToWatch->GetProcessDescription());
       m_WatcherList.push_back(watch);
       }
diff --git a/Modules/Wrappers/SWIG/src/itkBase.includes b/Modules/Wrappers/SWIG/src/itkBase.includes
index d9f1d3573371324b5fd4b8532d1a049059be70f6..673a86cfee49a6d705834bddb542b8e8eb79d1da 100644
--- a/Modules/Wrappers/SWIG/src/itkBase.includes
+++ b/Modules/Wrappers/SWIG/src/itkBase.includes
@@ -29,6 +29,8 @@
 
 #include "itkCommand.h"
 
+#include "itkLogOutput.h"
+
 typedef itk::LightObject                itkLightObject;
 typedef itk::LightObject::Pointer       itkLightObject_Pointer;
 typedef itk::Object                     itkObject;
@@ -60,4 +62,6 @@ typedef itk::EndPickEvent         itkEndPickEvent;
 typedef itk::AbortCheckEvent      itkAbortCheckEvent;
 typedef itk::UserEvent            itkUserEvent;
 
+typedef itk::LogOutput            itkLogOutput;
+
 #endif
diff --git a/Modules/Wrappers/SWIG/src/otbApplication.i b/Modules/Wrappers/SWIG/src/otbApplication.i
index 63c629d99e3e7a88158958061b30e2b1d03bbb44..6f84595c2462083646ae6a559896e058831c0e66 100644
--- a/Modules/Wrappers/SWIG/src/otbApplication.i
+++ b/Modules/Wrappers/SWIG/src/otbApplication.i
@@ -203,6 +203,13 @@ public:
 
 } // end of namespace otb
 
+#if SWIGPYTHON
+
+
+%include "otbPythonLogOutput.i"
+#endif
+
+
 class Application: public itkObject
 {
 public:
@@ -217,6 +224,31 @@ public:
   int Execute();
   int ExecuteAndWriteOutput();
 
+#if SWIGPYTHON
+  Logger* GetLogger();
+#endif
+  unsigned long itk::Object::AddObserver(const EventObject & event, 
+                                          Command * command);
+
+
+#if SWIGPYTHON
+  %extend 
+    {
+    /** SetupLogger : Add the PythonLogOutput and setup the progress 
+     * reporting for the application */
+    %pythoncode
+      {
+      def SetupLogger(self):
+          logger = self.GetLogger()
+          logger.AddLogOutput(_libraryLogOutput.GetPointer())
+          
+          self.AddObserver(AddProcessToWatchEvent(),
+                           _libraryProgressReportManager.GetAddProcessCommand()
+                          )
+      }
+    }
+#endif // SWIGPYTHON
+
   std::vector<std::string> GetParametersKeys(bool recursive = true);
   Parameter* Application::GetParameterByKey(std::string name);
   std::string GetParameterName(std::string);
@@ -877,7 +909,21 @@ class Registry : public itkObject
 public:
 
   static std::vector<std::string> GetAvailableApplications();
+  #if SWIGPYTHON
+  %rename("CreateApplicationWithoutLogger") CreateApplication;
+  static Application_Pointer CreateApplication(const std::string& name);
+  %pythoncode
+  {
+    @staticmethod
+    def CreateApplication(name):
+        application = _otbApplication.Registry_CreateApplicationWithoutLogger(name)
+        if application is not None:
+            application.SetupLogger()
+        return application
+  }
+  #else
   static Application_Pointer CreateApplication(const std::string& name);
+  #endif
   static void AddApplicationPath(std::string newpath);
   static void SetApplicationPath(std::string newpath);
   static void CleanRegistry();
diff --git a/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i
new file mode 100644
index 0000000000000000000000000000000000000000..4bd7852b2ee7540e8cacb172ecbca7ba2d376ffa
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/otbPythonLogOutput.i
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if SWIGPYTHON
+
+%module(directors="1") cb
+%{
+   #include "otbPythonLogOutput.h"
+   #include "otbSwigPrintCallback.h"
+%}
+
+%feature("director") SwigPrintCallback;
+
+%include "otbSwigPrintCallback.h"
+
+class itkLogOutput : public itkObject
+{
+protected:
+  itkLogOutput();
+  ~itkLogOutput();
+};
+
+/** This Callback class can be called from C++ to print, flush and to determine
+ * if stdout is redirected */
+%pythoncode
+  {
+  class PythonPrintCallback(SwigPrintCallback):
+      def __init__(self):
+          super(PythonPrintCallback, self).__init__()
+      def Call(self, content):
+          sys.stdout.write(content)
+      def Flush(self):
+          sys.stdout.flush()
+      def IsInteractive(self):
+          return sys.stdout.isatty()
+  }
+
+class PythonLogOutput : public itkLogOutput
+{
+public:
+  static PythonLogOutput_Pointer New();
+  virtual void Delete();
+  void SetCallback(otb::SwigPrintCallback* callback);
+  virtual void Write(std::string const & content);
+
+protected:
+  PythonLogOutput();
+};
+
+DECLARE_REF_COUNT_CLASS( PythonLogOutput )
+
+class Logger
+{
+public:
+  virtual void AddLogOutput(itkLogOutput *output);
+  static Logger * Instance();
+  void ResetOutputs();
+protected:
+  Logger();
+  virtual ~Logger();
+
+};
+
+class ProgressReporterManager: public itkObject
+{
+public:
+  /** Default constructor */
+  
+  static ProgressReporterManager_Pointer New();
+  virtual void Delete();
+  void DeleteWatcherList();
+  void SetLogOutputCallback(otb::SwigPrintCallback* callback);
+  itkCommand* GetAddProcessCommand();
+  
+protected:
+  ProgressReporterManager();
+};
+
+DECLARE_REF_COUNT_CLASS( ProgressReporterManager )
+
+/** Create the required objects for logging. Logger.Instance() is reset in 
+ * order to replace the itkStdStreamLogOutput by a PythonLogOutput */
+%pythoncode {
+  _libraryLogOutput = PythonLogOutput_New()
+  _libraryLogCallback = PythonPrintCallback()
+  _libraryProgressReportManager = ProgressReporterManager_New()
+  
+  Logger.Instance().ResetOutputs()
+  _libraryLogOutput.SetCallback(_libraryLogCallback)
+  Logger.Instance().AddLogOutput(_libraryLogOutput.GetPointer())
+  
+  _libraryProgressReportManager.SetLogOutputCallback(_libraryLogCallback)
+
+}
+
+#endif
diff --git a/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h b/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h
index 3e1bbf56d7e7ac7f58089754e7464bf56bdbe37a..603910cc06fbbbcd359580d744d7de7618ca2ce5 100644
--- a/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h
+++ b/Modules/Wrappers/SWIG/src/otbWrapperSWIGIncludes.h
@@ -39,4 +39,18 @@ typedef otb::Wrapper::ComplexInputImageParameter         ComplexInputImageParame
 
 typedef otb::Wrapper::ImageBaseType                      ImageBaseType;
 
+#if defined(SWIGPYTHON)
+#include "otbPythonLogOutput.h"
+#include "otbLogger.h"
+#include "otbProgressReporterManager.h"
+
+typedef otb::Logger                           Logger;
+typedef otb::Logger::Pointer                  Logger_Pointer;
+typedef otb::SwigPrintCallback                SwigPrintCallback;
+typedef otb::PythonLogOutput                  PythonLogOutput;
+typedef otb::PythonLogOutput::Pointer         PythonLogOutput_Pointer;
+typedef otb::ProgressReporterManager          ProgressReporterManager;
+typedef otb::ProgressReporterManager::Pointer ProgressReporterManager_Pointer;
+#endif
+
 #endif
diff --git a/Modules/Wrappers/SWIG/src/python/CMakeLists.txt b/Modules/Wrappers/SWIG/src/python/CMakeLists.txt
index 01d94c050f07eb3e9f592155824d0a117a9497f7..6a7b288b5cb9ea944662a3fccaf88c4b1181be0c 100644
--- a/Modules/Wrappers/SWIG/src/python/CMakeLists.txt
+++ b/Modules/Wrappers/SWIG/src/python/CMakeLists.txt
@@ -32,8 +32,15 @@ set(SWIG_MODULE_otbApplication_EXTRA_DEPS
      ${CMAKE_CURRENT_SOURCE_DIR}/../Python.i
      ${CMAKE_CURRENT_SOURCE_DIR}/../PyCommand.i
      itkPyCommand.h
+     otbSwigPrintCallback.h
+     otbPythonLogOutput.h
+     otbProgressReporterManager.h
      OTBApplicationEngine)
-SWIG_add_module( otbApplication python ../otbApplication.i otbApplicationPYTHON_wrap.cxx itkPyCommand.cxx )
+SWIG_add_module( otbApplication python ../otbApplication.i 
+                                        otbApplicationPYTHON_wrap.cxx 
+                                        itkPyCommand.cxx
+                                        ../python/otbPythonLogOutput.cxx
+                                        ../python/otbProgressReporterManager.cxx)
 SWIG_link_libraries( otbApplication ${PYTHON_LIBRARIES} OTBApplicationEngine )
 set_target_properties(_otbApplication PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SWIG_OUTDIR})
 
diff --git a/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e3a6ac541739b337fea15b1597a186b559031042
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.cxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbProgressReporterManager.h"
+#include "otbWrapperAddProcessToWatchEvent.h"
+
+namespace otb
+{
+
+ProgressReporterManager::ProgressReporterManager()
+{
+  // Add the callback to be added when a AddProcessToWatch event is invoked
+  m_AddProcessCommand = AddProcessCommandType::New();
+  m_AddProcessCommand->SetCallbackFunction(this, &ProgressReporterManager::LinkWatchers);
+}
+
+ProgressReporterManager::~ProgressReporterManager()
+{
+  this->DeleteWatcherList();
+}
+
+void ProgressReporterManager::DeleteWatcherList()
+{
+  //Delete all stored progress reporter
+  for (auto watcher: m_WatcherList)
+  {
+    delete watcher;
+  }
+  m_WatcherList.clear();
+}
+
+void ProgressReporterManager::LinkWatchers(itk::Object* itkNotUsed(caller), const itk::EventObject& event)
+{
+  if (typeid(otb::Wrapper::AddProcessToWatchEvent) == typeid(event))
+  {
+    const Wrapper::AddProcessToWatchEvent* eventToWatch = dynamic_cast<const Wrapper::AddProcessToWatchEvent*>(&event);
+
+    auto watch = new WatcherType(eventToWatch->GetProcess(), eventToWatch->GetProcessDescription());
+    watch->SetCallback(m_Callback);
+    m_WatcherList.push_back(watch);
+  }
+}
+}
diff --git a/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec15926fd20ad0b91ac238f0fbc1b7e61b0e4c1b
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/python/otbProgressReporterManager.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbProgressReporterManager_h
+#define otbProgressReporterManager_h
+
+#include "itkCommand.h"
+#include "otbWrapperApplication.h"
+
+#include "otbSwigPrintCallback.h"
+#include "otbStandardOneLineFilterWatcher.h"
+
+namespace otb
+{
+
+/** \class ProgressReporterManager
+ *  \brief Class to manage progress reporting with callback printing.
+ *
+ *  This class stores the command used to create CallbackProgressReporter
+ *  using an Observer. The created CallbackProgressReporter are also stored
+ *  in this class.
+ */
+class ProgressReporterManager : public itk::Object
+{
+public:
+  /** Standard class typedefs. */
+  typedef ProgressReporterManager       Self;
+  typedef itk::Object                   Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  itkTypeMacro(ProgressReporterManager, itk::Object);
+
+  itkNewMacro(ProgressReporterManager);
+
+  typedef SwigPrintCallback CallbackType;
+  typedef StandardOneLineFilterWatcher<CallbackType> WatcherType;
+  
+  /** Filter watcher list type */
+  typedef std::vector<WatcherType *> WatcherListType;
+
+  /** Command Member */
+  typedef itk::MemberCommand<Self> AddProcessCommandType;
+
+  /** Set the logger callback function */
+  void SetLogOutputCallback(CallbackType* callback)
+  {
+    m_Callback = callback;
+    this->Modified();
+  }
+
+  /** Getter to AddProcessCommand */
+  AddProcessCommandType* GetAddProcessCommand()
+  {
+    return m_AddProcessCommand.GetPointer();
+  }
+
+  /** Delete all watchers */
+  void DeleteWatcherList();
+
+protected:
+  /** Default constructor */
+  ProgressReporterManager();
+
+  /** Destructor. */
+  ~ProgressReporterManager() override;
+
+  /** Load the watchers for internal progress and writing progress report. */
+  void LinkWatchers(itk::Object* caller, const itk::EventObject& event);
+
+private:
+  /** The LogOutputCallback used for printing */
+  CallbackType* m_Callback;
+
+  /** Command associated to the LinkWatchers command */
+  AddProcessCommandType::Pointer m_AddProcessCommand;
+
+  /** container storing all the watchers (CallbackProgressReporter) */
+  WatcherListType m_WatcherList;
+};
+}
+
+#endif // otbProgressReporterManager_h
diff --git a/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d8f703c4b8d1eb4b2f6a932d7e02c0a648b6fc15
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.cxx
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbPythonLogOutput.h"
+
+namespace otb
+{
+void PythonLogOutput::Flush()
+{
+  m_Callback->Flush();
+}
+
+void PythonLogOutput::Write(double timestamp)
+{
+  m_Callback->Call(std::to_string(timestamp));
+}
+
+void PythonLogOutput::Write(std::string const& content)
+{
+  m_Callback->Call(content);
+}
+
+void PythonLogOutput::Write(std::string const& content, double timestamp)
+{
+  m_Callback->Call(std::to_string(timestamp) + " : " + content);
+}
+
+void PythonLogOutput::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+
+} // namespace otb
diff --git a/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8e8cfeed22a8f9a04dba0612bda6e4d3259eaf2
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/python/otbPythonLogOutput.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbPythonLogOutput_h
+#define otbPythonLogOutput_h
+
+#include "itkLogOutput.h"
+#include "otbSwigPrintCallback.h"
+
+namespace otb
+{
+
+/** \class LogOutputCallback
+ *  \brief A itk::LogOutput using a LogOutputCallback
+ *
+ *  This class delegates the Write and Flush methods to a LogOutputCallback
+ */
+class PythonLogOutput : public itk::LogOutput
+{
+public:
+  typedef PythonLogOutput               Self;
+  typedef itk::LogOutput                Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  typedef SwigPrintCallback CallbackType;
+  itkTypeMacro(PythonLogOutput, itk::LogOutput);
+
+  itkNewMacro(PythonLogOutput);
+
+  /** Set the callback method */
+  void SetCallback(CallbackType* callback)
+  {
+    m_Callback = callback;
+    this->Modified();
+  }
+
+  /** flush a buffer */
+  virtual void Flush() override;
+
+  /** Write to a buffer */
+  virtual void Write(double timestamp) override;
+
+  /** Write to a buffer */
+  virtual void Write(std::string const& content) override;
+
+  /** Write to a buffer */
+  virtual void Write(std::string const& content, double timestamp) override;
+
+protected:
+  /** Constructor */
+  PythonLogOutput() = default;
+
+  /** Destructor */
+  ~PythonLogOutput() override = default;
+
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const override;
+
+private:
+  CallbackType* m_Callback;
+};
+
+} // namespace otb
+
+#endif // otbPythonLogOutput_h
diff --git a/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h b/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h
new file mode 100644
index 0000000000000000000000000000000000000000..e17a0087304b94a4cb9947b5bc1d021711dc80e8
--- /dev/null
+++ b/Modules/Wrappers/SWIG/src/python/otbSwigPrintCallback.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbSwigPrintCallbackCallback_h
+#define otbSwigPrintCallbackCallback_h
+
+namespace otb
+{
+
+/** \class SwigPrintCallback
+ *  \brief Interface for a printing callback method
+ *
+ *  This class defines the Call method, used to write a string, the Flush
+ *  method, used to flush a bugger, and the Isatty method used to determine
+ *  if the output is interactive. This class is the base class of the Python
+ *  class PythonLogOutputCallback, that uses Swig directors to override these
+ *  methods.
+ */
+
+class SwigPrintCallback
+{
+public:
+  /** Constructor */
+  SwigPrintCallback() = default;
+
+  /** Destructor */
+  virtual ~SwigPrintCallback() = default;
+
+  /** Write a string to a buffer */
+  virtual void Call(std::string const&) {};
+
+  /** Flush the buffer */
+  virtual void Flush() {};
+
+  /** Determine if the bufer is interactive */
+  virtual bool IsInteractive() {return false;};
+};
+
+} // namespace otb
+
+#endif // otbPythonLogOutputCallback_h