diff --git a/ArchiveExtractor.py b/ArchiveExtractor.py
index 1c2c98c1614ca452bb13d4f900de7e3ac2669512..cd780d47c25fa95f474cd99c89e51ff89cc15bb9 100755
--- a/ArchiveExtractor.py
+++ b/ArchiveExtractor.py
@@ -13,473 +13,423 @@ import PyTango as tango
 
 __version__ = "1.0.1"
 
+class ArchiveExtractor:
 
-##########################################################################
-""" Commodity variables """
-
-# Extractor date format for GetAttDataBetweenDates
-DBDFMT = "%Y-%m-%d %H:%M:%S"
-
-# Extractor date format for GetNearestValue
-DBDFMT2 = "%d-%m-%Y %H:%M:%S"
-
-ArrayTimeStampToDatetime = np.vectorize(datetime.datetime.fromtimestamp)
-
-##---------------------------------------------------------------------------##
-def dateparse(datestr):
-    """
-    Convenient function to parse date strings.
-    Global format is %Y-%m-%d-%H:%M:%S and it can be reduced to be less precise.
-
-    Parameters
-    ---------
-    datestr : string
-        Date as a string, format %Y-%m-%d-%H:%M:%S or less precise.
-
-    Exceptions
-    ----------
-    ValueError
-        If the parsing failed.
-
-    Returns
-    -------
-    date : datetime.datetime
-        Parsed date
-    """
-    logger.info("Parse date '%s'"%datestr)
-
-    fmt = [
-        "%Y-%m-%d-%H:%M:%S",
-        "%Y-%m-%d-%H:%M",
-        "%Y-%m-%d-%H",
-        "%Y-%m-%d",
-        "%Y-%m",
-        ]
-
-    date = None
-    for f in fmt:
-        logger.debug("Try format '%s'"%f)
-        try:
-            date = datetime.datetime.strptime(datestr, f)
-        except ValueError:
-            logger.debug("Parsing failed")
-
-    if date is None:
-        logger.error("Could not parse date")
-        raise ValueError
-
-    return date
-
-##---------------------------------------------------------------------------##
-def query_ADB_BetweenDates(attr,
-              dateStart,
-              dateStop=datetime.datetime.now(),
-              extractor="archiving/TDBExtractor/4"):
-    """
-    Query attribute data from an archiver database, get all points between dates.
-    Use ExtractBetweenDates.
-
-    Parameters
-    ----------
-    attr : String
-        Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
-
-    dateStart : datetime.datetime
-        Start date for extraction.
-
-    dateStop : datetime.datetime
-        Stop date for extraction.
-        Default is now (datetime.datetime.now())
-
-    extractor : String
-        Name of the DB Extractor device.
-        Default is "archiving/TDBExtractor/4"
-
-    Exceptions
-    ----------
-    ValueError
-        The attribute is not found in the database.
-
-    Returns
-    -------
-    [date, value] : array
-        date : numpy.ndarray of datetime.datime objects
-            Dates of the values
-        value : numpy.ndarray
-            Archived values
-
-    """
-
-    # Max number of point per extraction chunks
-    Nmax = 100000
-
-    # Device Proxy to DB
-    logger.debug("Instantiate proxy to %s"%extractor)
-    ADB = tango.DeviceProxy(extractor)
-
-    # Give the DB extractor 3 seconds timeout
-    ADB.set_timeout_millis(3000)
-
-    # Check that the attribute is in the database
-    logger.debug("Check that %s is archived."%attr)
-    if not ADB.IsArchived(attr):
-        logger.error("Attribute '%s' is not archived in DB %s"%(attr, extractor))
-        raise ValueError("Attribute '%s' is not archived in DB %s"%(attr, extractor))
-
-    # Get its sampling period in seconds
-    req=ADB.GetArchivingMode(attr)
-    logger.debug("GetArchivingMode: "+str(req))
-
-    if req[0] == "MODE_P":
-        samplingPeriod = int(req[1])*10**-3
-        logger.debug("Attribute is sampled every %g seconds"%samplingPeriod)
-
-    elif req[0] == "MODE_EVT":
-        logger.warning("Attribute is archived on event. Chunks of data are sized with an estimated datarate of 0.1Hz")
-        samplingPeriod = 10
-
-    else:
-        raise NotImplemented("Archive mode not implemented")
-
-
-    # Evaluate the number of points
-    est_N = (dateStop-dateStart).total_seconds()/samplingPeriod
-    logger.debug("Which leads to %d points to extract."%est_N)
-
-    # If data chunk is too much, we need to cut it
-    if est_N > Nmax:
-        dt = datetime.timedelta(seconds=samplingPeriod)*Nmax
-        cdates = [dateStart]
-        while cdates[-1] < dateStop:
-            cdates.append(cdates[-1]+dt)
-        cdates[-1] = dateStop
-        logger.debug("Cutting access to %d little chunks of time, %s each."%(len(cdates)-1, dt))
-    else:
-        cdates=[dateStart, dateStop]
-
-    # Arrays to hold every chunks
-    value = []
-    date = []
-
-    # For each date chunk
-    for i_d in range(len(cdates)-1):
-        # Make retrieval request
-        logger.debug("Perform ExtractBetweenDates (%s, %s, %s)"%(
-            attr,
-            cdates[i_d].strftime(DBDFMT),
-            cdates[i_d+1].strftime(DBDFMT))
-            )
-
-        _date, _value = ADB.ExtractBetweenDates([
-            attr,
-            cdates[i_d].strftime(DBDFMT),
-            cdates[i_d+1].strftime(DBDFMT)
-            ])
-
-        # Transform to datetime - value arrays
-        _value = np.asarray(_value, dtype=float)
-        if len(_date) > 0:
-            _date = ArrayTimeStampToDatetime(_date/1000.0)
-
-        value.append(_value)
-        date.append(_date)
-
-    logger.debug("Concatenate chunks")
-    value = np.concatenate(value)
-    date = np.concatenate(date)
-
-
-    logger.debug("Extraction done for %s."%attr)
-    return [date, value]
-
-##---------------------------------------------------------------------------##
-def query_ADB_BetweenDates_MinMaxMean(
-                                        attr,
-                                        dateStart,
-                                        dateStop=datetime.datetime.now(),
-                                        timeinterval=datetime.timedelta(seconds=60),
-                                        extractor="archiving/TDBExtractor/4"):
-    """
-    Query attribute data from archiver database.
-    Divide the time range in time intervals.
-    Get min, max and mean value on each time interval.
-    The date stamp is in the middle of the interval.
-
-    Parameters
-    ----------
-    attr : String
-        Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
-
-    dateStart : datetime.datetime
-        Start date for extraction.
-
-    dateStop : datetime.datetime
-        Stop date for extraction.
-        Default is now (datetime.datetime.now())
-
-    timeinterval : datetime.timedelta
-        Interval time to divide the time range in chunks.
-        Default is 1 minute.
-
-    extractor : String
-        Name of the DB Extractor device.
-        Default is "archiving/TDBExtractor/4"
-
-    Exceptions
-    ----------
-    ValueError
-        The attribute is not found in the database.
-
-    Returns
-    -------
-    [date, value] : array
-        date : numpy.ndarray of datetime.datime objects
-            Dates of the values
-        value : numpy.ndarray
-            Archived values
-
-    """
-
-    # TEMP Dev not finished
-    logger.error("Feature not implemented yet.")
-    return
-
-    # Device Proxy to DB
-    logger.debug("Instantiate proxy to %s"%extractor)
-    ADB = tango.DeviceProxy(extractor)
-
-    # Give the DB extractor 3 seconds timeout
-    ADB.set_timeout_millis(3000)
-
-    # Check that the attribute is in the database
-    logger.debug("Check that %s is archived."%attr)
-    if not ADB.IsArchived(attr):
-        logger.error("Attribute '%s' is not archived in DB %s"%(attr, extractor))
-        raise ValueError("Attribute '%s' is not archived in DB %s"%(attr, extractor))
-
-    # Cut data range in time chunks
-    cdates = [dateStart]
-    while cdates[-1] < dateStop:
-        cdates.append(cdates[-1]+timeinterval)
-    cdates[-1] = dateStop
-    logger.debug("Cutting time range to %d chunks of time, %s each."%(len(cdates)-1, dt))
-
-    # Prepare arrays
-    value_min = np.empty(len(cdates-1))
-    value_max = np.empty(len(cdates-1))
-    value_mean = np.empty(len(cdates-1))
-
-    # For each time chunk
-    for i_d in range(len(cdates)-1):
-        # Make requests
-        logger.debug("Perform GetAttDataMaxBetweenDates (%s, %s, %s)"%(
-            attr,
-            cdates[i_d].strftime(DBDFMT),
-            cdates[i_d+1].strftime(DBDFMT))
-            )
-
-        ADB.GetAttDataMaxBetweenDates([
-            attr,
-            cdates[i_d].strftime(DBDFMT),
-            cdates[i_d+1].strftime(DBDFMT)
-            ])
+    ##########################################################################
+    """ Commodity variables """
 
+    # Extractor date format for GetAttDataBetweenDates
+    DBDFMT = "%Y-%m-%d %H:%M:%S"
 
-##---------------------------------------------------------------------------##
-def query_ADB_NearestValue(attr,
-                            dates,
-                            extractor="archiving/TDBExtractor/4"):
-    """
-    Query attribute data from an archiver database, get nearest points from dates.
-    Use GetNearestValue and perform multiple calls.
-    For each date in dates, it read the closest sampled value.
-    Return the real dates of the samples.
+    # Extractor date format for GetNearestValue
+    DBDFMT2 = "%d-%m-%Y %H:%M:%S"
 
-    Parameters
-    ----------
-    attr : String
-        Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
+    # Vectorized fromtimestamp function
+    ArrayTimeStampToDatetime = np.vectorize(datetime.datetime.fromtimestamp)
 
-    dates : numpy.ndarray of datetime.datetime
-        Dates for extraction.
-
-    extractor : String
-        Name of the DB Extractor device.
-        Default is "archiving/TDBExtractor/4"
-
-    Exceptions
-    ----------
-    ValueError
-        The attribute is not found in the database.
-
-    Returns
-    -------
-    [realdate, value] : array
-        realdate : numpy.ndarray of datetime.datime objects
-            Dates of the values
-        value : numpy.ndarray
-            Archived values
-
-    """
-
-    # Device Proxy to DB
-    ADB = tango.DeviceProxy(extractor)
-
-    # Give the DB extractor 3 seconds timeout
-    ADB.set_timeout_millis(3000)
-
-    # Check that the attribute is in the database
-    if not ADB.IsArchived(attr):
-        raise ValueError("Attribute '%s' is not archived in DB %s"%(attr, extractor))
-
-    # Prepare arrays
-    value = np.empty(len(dates), dtype=float)
-    realdate = np.empty(len(dates), dtype=object)
+    # Max number of point per extraction chunks
+    Nmax = 100000
 
-    # Loop on dates
-    for i in range(len(dates)):
-        # Make retrieval
+    ##########################################################################
+    def __init__(
+            self,
+            ExtractorKind='H', ExtractorNumber=2,
+            ExtractorPath=None,
+            logger=logging.getLogger("ArchiveExtractor")
+            ):
+        """
+        Constructor function
+
+        Parameters
+        ----------
+        ExtractorKind: char
+            Either 'H' or 'T' for HDB or TDB.
+
+        ExtractorNumber: int
+            Number of the archive extractor instance to use.
+
+        ExtractorPath: string
+            Tango path to the extractor.
+            If this argument is given, it takes precedence over ExtractorKind and ExtractorNumber.
+
+        logger: logging.Logger
+            Logger object to use
+
+        Return
+        ------
+        ArchiveExtractor
+        """
+
+        # Get logger
+        self.logger = logger
+
+        #######################################################
+        # Select Extractor
+        if ExtractorPath is None:
+            self.extractor = "archiving/%sDBExtractor/%d"%(ExtractKind, ExtractorNumber)
+        else:
+            self.extractor = tango.DeviceProxy(ExtractorPath)
+
+        self.extractor.set_timeout_millis(3000)
+        self.logger.debug("Archive Extractor %s used."%self.extractor.name())
+
+    ##---------------------------------------------------------------------------##
+    @staticmethod
+    def dateparse(datestr):
+        """
+        Convenient function to parse date strings.
+        Global format is %Y-%m-%d-%H:%M:%S and it can be reduced to be less precise.
+
+        Parameters
+        ---------
+        datestr : string
+            Date as a string, format %Y-%m-%d-%H:%M:%S or less precise.
+
+        Exceptions
+        ----------
+        ValueError
+            If the parsing failed.
+
+        Returns
+        -------
+        date : datetime.datetime
+            Parsed date
+        """
+
+        # This gives all format that will be tried, in order.
+        # Stop on first parse success. Raise error if none succeed.
+        fmt = [
+            "%Y-%m-%d-%H:%M:%S",
+            "%Y-%m-%d-%H:%M",
+            "%Y-%m-%d-%H",
+            "%Y-%m-%d",
+            "%Y-%m",
+            ]
+
+        date = None
+        for f in fmt:
+            try:
+                date = datetime.datetime.strptime(datestr, f)
+            except ValueError:
+                continue
+            else:
+                break
+        else:
+            raise ValueError("Could not parse argument to a date")
 
-        answ = ADB.GetNearestValue([attr, dates[i].strftime(DBDFMT2)])
-        answ = answ.split(";")
+        return date
 
-        realdate[i] = datetime.datetime.fromtimestamp(int(answ[0])/1000)
-        value[i] = answ[1]
 
-    return [realdate, value]
+    ##---------------------------------------------------------------------------##
+    def evalPoints(
+            self,
+            attribute,
+            dateStart,
+            dateStop,
+            ):
+        """
+        Evaluate the number of points for the attribute on the date range.
+        Also checks for its presence.
 
+        Parameters
+        ----------
+        attribute : String
+            Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
 
+        dateStart : datetime.datetime
+            Start date for extraction.
 
-##########################################################################
-""" Command Line Interface """
-if __name__ == "__main__":
+        dateStop : datetime.datetime
+            Stop date for extraction.
+            Default is now (datetime.datetime.now())
 
-    # Name the logger after the filename
-    logger = logging.getLogger("ArchiveExtractor")
+        Exceptions
+        ----------
+        ValueError
+            The attribute is not found in the database.
 
-    # Default stop date
-    dateStop = datetime.datetime.now()
+        NotImplemented
+            The archive mode returned by the DB is not handled.
 
-    # Default stop date
-    dateStart = datetime.datetime.now()-datetime.timedelta(days=1)
 
-    #######################################################
-    # Install argument parser
-    import argparse
+        Return
+        ------
+        N: int
+            Number of points on the date range.
 
-    parser = argparse.ArgumentParser(description="Extract attributes from the extractor devices.\nVersion %s"%__version__)
+        """
+        # Check that the attribute is in the database
+        self.logger.debug("Check that %s is archived."%attribute)
+        if not self.extractor.IsArchived(attribute):
+            self.logger.error("Attribute '%s' is not archived in DB %s"%(attribute, extractor))
+            raise ValueError("Attribute '%s' is not archived in DB %s"%(attribute, extractor))
 
-    parser.add_argument("--from", type=dateparse, dest="dateStart",
-        help="Start date for extraction, format '1990-12-13-22:33:45'. "+
-        "It is possible to be less precise and drop, seconds, minutes, hours or even day."+
-        " Default is one day ago",
-        default=dateStart)
+        # Get its sampling period in seconds
+        req=self.extractor.GetArchivingMode(attribute)
+        self.logger.debug("GetArchivingMode: "+str(req))
 
-    parser.add_argument("--to", type=dateparse, dest="dateStop",
-        help="Stop date for extraction, format '1990-12-13-22:33:45'. It is possible to be less precise and drop, seconds, minutes, hours or even day."+
-        " Default is now.",
-        default=dateStop)
+        if req[0] == "MODE_P":
+            samplingPeriod = int(req[1])*10**-3
+            self.logger.debug("Attribute is sampled every %g seconds"%samplingPeriod)
 
-    parser.add_argument("--DB", choices=["H", "T", "L"],
-        default="T", help="Database to extract from. HDB (H) or TDB (T), default: %(default)s")
+        elif req[0] == "MODE_EVT":
+            self.logger.warning("Attribute is archived on event. Chunks of data are sized with an estimated datarate of 0.1Hz")
+            samplingPeriod = 10
 
-    parser.add_argument("--DBN", type=int, default=2,
-            help="Extractor device number, default: %(default)s")
+        else:
+            self.logger.error("Archive mode not implemented in this script")
+            raise NotImplemented("Archive mode not implemented in this script")
 
-    parser.add_argument("--fileout", type=str, default="extracted_%s.npy"%datetime.datetime.now().strftime("%Y%m%d_%H%M%S"),
-            help="filename of the extraction destination. Default: %(default)s"),
 
-    parser.add_argument('--log', type=str, default="INFO",
-            help="Log level. Default: %(default)s.")
+        # Evaluate the number of points
+        N = (dateStop-dateStart).total_seconds()/samplingPeriod
+        self.logger.debug("Which leads to %d points to extract."%est_N)
 
+        return N
 
-    parser.add_argument('--filemode', action="store_true",
-            help="Set attribute to filemode."+
-            " Instead of specifying attributes, put a path to a file containing a list of attributes."+
-            " The file contains one attribute per line.")
 
-    parser.add_argument('attributes', type=str, nargs='+',
-                        help="List of attributes to extract. Full tango path.")
 
-    args = parser.parse_args()
+    ##---------------------------------------------------------------------------##
+    def BetweenDates(
+            self,
+            attr,
+            dateStart,
+            dateStop=datetime.datetime.now(),
+            ):
+        """
+        Query attribute data from an archiver database, get all points between dates.
+        Use ExtractBetweenDates.
+
+        Parameters
+        ----------
+        attr : String
+            Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
+
+        dateStart : datetime.datetime
+            Start date for extraction.
+
+        dateStop : datetime.datetime
+            Stop date for extraction.
+            Default is now (datetime.datetime.now())
+
+        Exceptions
+        ----------
+        ValueError
+            The attribute is not found in the database.
+
+        Returns
+        -------
+        [date, value] : array
+            date : numpy.ndarray of datetime.datime objects
+                Dates of the values
+            value : numpy.ndarray
+                Archived values
+
+        """
+
+        # Check and estimate the number of points
+        est_N = self.evalPoints(attribute, dateStart, dateStop)
+
+        # If data chunk is too much, we need to cut it
+        if est_N > Nmax:
+            dt = datetime.timedelta(seconds=samplingPeriod)*Nmax
+            cdates = [dateStart]
+            while cdates[-1] < dateStop:
+                cdates.append(cdates[-1]+dt)
+            cdates[-1] = dateStop
+            self.logger.debug("Cutting access to %d little chunks of time, %s each."%(len(cdates)-1, dt))
+        else:
+            cdates=[dateStart, dateStop]
+
+        # Arrays to hold every chunks
+        value = []
+        date = []
+
+        # For each date chunk
+        for i_d in range(len(cdates)-1):
+            # Make retrieval request
+            self.logger.debug("Perform ExtractBetweenDates (%s, %s, %s)"%(
+                attr,
+                cdates[i_d].strftime(DBDFMT),
+                cdates[i_d+1].strftime(DBDFMT))
+                )
+
+            _date, _value = self.extractor.ExtractBetweenDates([
+                attr,
+                cdates[i_d].strftime(DBDFMT),
+                cdates[i_d+1].strftime(DBDFMT)
+                ])
+
+            # Transform to datetime - value arrays
+            _value = np.asarray(_value, dtype=float)
+            if len(_date) > 0:
+                _date = ArrayTimeStampToDatetime(_date/1000.0)
+
+            value.append(_value)
+            date.append(_date)
+
+        self.logger.debug("Concatenate chunks")
+        value = np.concatenate(value)
+        date = np.concatenate(date)
+
+
+        self.logger.debug("Extraction done for %s."%attr)
+        return [date, value]
+
+    ##---------------------------------------------------------------------------##
+    def query_ADB_BetweenDates_MinMaxMean(
+                                            attr,
+                                            dateStart,
+                                            dateStop=datetime.datetime.now(),
+                                            timeinterval=datetime.timedelta(seconds=60),
+                                            extractor="archiving/TDBExtractor/4"):
+        """
+        Query attribute data from archiver database.
+        Divide the time range in time intervals.
+        Get min, max and mean value on each time interval.
+        The date stamp is in the middle of the interval.
+
+        Parameters
+        ----------
+        attr : String
+            Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
+
+        dateStart : datetime.datetime
+            Start date for extraction.
+
+        dateStop : datetime.datetime
+            Stop date for extraction.
+            Default is now (datetime.datetime.now())
+
+        timeinterval : datetime.timedelta
+            Interval time to divide the time range in chunks.
+            Default is 1 minute.
+
+        extractor : String
+            Name of the DB Extractor device.
+            Default is "archiving/TDBExtractor/4"
+
+        Exceptions
+        ----------
+        ValueError
+            The attribute is not found in the database.
+
+        Returns
+        -------
+        [date, value] : array
+            date : numpy.ndarray of datetime.datime objects
+                Dates of the values
+            value : numpy.ndarray
+                Archived values
+
+        """
+
+        # TEMP Dev not finished
+        logger.error("Feature not implemented yet.")
+        return
+
+        # Device Proxy to DB
+        logger.debug("Instantiate proxy to %s"%extractor)
+        ADB = tango.DeviceProxy(extractor)
+
+        # Give the DB extractor 3 seconds timeout
+        ADB.set_timeout_millis(3000)
+
+        # Check that the attribute is in the database
+        logger.debug("Check that %s is archived."%attr)
+        if not ADB.IsArchived(attr):
+            logger.error("Attribute '%s' is not archived in DB %s"%(attr, extractor))
+            raise ValueError("Attribute '%s' is not archived in DB %s"%(attr, extractor))
+
+        # Cut data range in time chunks
+        cdates = [dateStart]
+        while cdates[-1] < dateStop:
+            cdates.append(cdates[-1]+timeinterval)
+        cdates[-1] = dateStop
+        logger.debug("Cutting time range to %d chunks of time, %s each."%(len(cdates)-1, dt))
 
+        # Prepare arrays
+        value_min = np.empty(len(cdates-1))
+        value_max = np.empty(len(cdates-1))
+        value_mean = np.empty(len(cdates-1))
 
-    #######################################################
-    # Configure logger
+        # For each time chunk
+        for i_d in range(len(cdates)-1):
+            # Make requests
+            logger.debug("Perform GetAttDataMaxBetweenDates (%s, %s, %s)"%(
+                attr,
+                cdates[i_d].strftime(DBDFMT),
+                cdates[i_d+1].strftime(DBDFMT))
+                )
 
-    # Add a stream handler
-    s_handler = logging.StreamHandler()
-    s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s"))
+            ADB.GetAttDataMaxBetweenDates([
+                attr,
+                cdates[i_d].strftime(DBDFMT),
+                cdates[i_d+1].strftime(DBDFMT)
+                ])
 
-    # Set level according to command line attribute
-    s_handler.setLevel(level=getattr(logging, args.log.upper()))
-    logger.setLevel(level=getattr(logging, args.log.upper()))
-    logger.addHandler(s_handler)
 
-    logger.debug("Parsed arguments: %s"%args)
+    ##---------------------------------------------------------------------------##
+    def query_ADB_NearestValue(attr,
+                                dates,
+                                extractor="archiving/TDBExtractor/4"):
+        """
+        Query attribute data from an archiver database, get nearest points from dates.
+        Use GetNearestValue and perform multiple calls.
+        For each date in dates, it read the closest sampled value.
+        Return the real dates of the samples.
 
-    logger.info("Archive Extractor %s"%__version__)
+        Parameters
+        ----------
+        attr : String
+            Name of the attribute. Full Tango name i.e. "test/dg/panda/current".
 
-    #######################################################
-    # Filemode or not
-    if args.filemode:
-        logger.info("Filemode, openning file %s"%args.attributes[0])
-        # Read the file. Each line is an attribute
-        with open(args.attributes[0], "r") as fp:
-            attributes = fp.readlines()
+        dates : numpy.ndarray of datetime.datetime
+            Dates for extraction.
 
-        logger.debug("Read lines : %s"%attributes)
+        extractor : String
+            Name of the DB Extractor device.
+            Default is "archiving/TDBExtractor/4"
 
-        # Clean end of line
-        for i_a in range(len(attributes)):
-            attributes[i_a] = attributes[i_a].rstrip()
+        Exceptions
+        ----------
+        ValueError
+            The attribute is not found in the database.
 
-    else:
-        attributes = args.attributes
+        Returns
+        -------
+        [realdate, value] : array
+            realdate : numpy.ndarray of datetime.datime objects
+                Dates of the values
+            value : numpy.ndarray
+                Archived values
 
-    #######################################################
-    # Select Extractor
-    if args.DB == "L":
-        extractor = "archiving/extractor/%d"%(args.DBN)
-    else:
-        extractor = "archiving/%sDBExtractor/%d"%(args.DB, args.DBN)
+        """
 
-    #######################################################
-    # Prepare dictionnary for result
-    results = dict()
+        # Device Proxy to DB
+        ADB = tango.DeviceProxy(extractor)
 
-    #######################################################
-    # Extract from database
-    logger.info("Extract from %s to %s."%(args.dateStart, args.dateStop))
+        # Give the DB extractor 3 seconds timeout
+        ADB.set_timeout_millis(3000)
 
-    for attr in attributes:
-        logger.info("Extracting attribute %s..."%attr)
+        # Check that the attribute is in the database
+        if not ADB.IsArchived(attr):
+            raise ValueError("Attribute '%s' is not archived in DB %s"%(attr, extractor))
 
-        for attempt in range(3):
-            try:
-                datevalue = query_ADB_BetweenDates(attr, args.dateStart, args.dateStop, extractor)
+        # Prepare arrays
+        value = np.empty(len(dates), dtype=float)
+        realdate = np.empty(len(dates), dtype=object)
 
-                # Add to result dictionnary
-                results[attr] = datevalue
+        # Loop on dates
+        for i in range(len(dates)):
+            # Make retrieval
 
-            except ValueError as e:
-                logger.debug("ErrorMsg: %s"%e)
-                logger.warning("Failed to extract %s. Skipping..."%attr)
-            except (tango.CommunicationFailed, tango.DevFailed) as e:
-                # retry
-                logger.debug("ErrorMsg: %s"%e)
-                logger.warning("Failed to extract %s. Retry..."%attr)
-            break
+            answ = ADB.GetNearestValue([attr, dates[i].strftime(DBDFMT2)])
+            answ = answ.split(";")
 
-        else:
-            logger.error("The device %s might have crash.\n"%extractor+
-                    "You should check with Jive and probably restart with Astor.\n")
+            realdate[i] = datetime.datetime.fromtimestamp(int(answ[0])/1000)
+            value[i] = answ[1]
 
-        # Save all at each step
-        np.save(args.fileout, results)
+        return [realdate, value]
 
-    logger.info("Extraction done, saved in file %s"%args.fileout)
 
-else:
-    # Name the logger after the module name
-    logger = logging.getLogger(__name__)
diff --git a/cli_archiveextractor.py b/cli_archiveextractor.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c90d5a83fae3a59b3af9e8acfdfa369cde62dd7
--- /dev/null
+++ b/cli_archiveextractor.py
@@ -0,0 +1,135 @@
+
+
+##########################################################################
+""" Command Line Interface """
+if __name__ == "__main__":
+
+    # Name the logger after the filename
+    logger = logging.getLogger("ArchiveExtractor")
+
+    # Default stop date
+    dateStop = datetime.datetime.now()
+
+    # Default stop date
+    dateStart = datetime.datetime.now()-datetime.timedelta(days=1)
+
+    #######################################################
+    # Install argument parser
+    import argparse
+
+    parser = argparse.ArgumentParser(description="Extract attributes from the extractor devices.\nVersion %s"%__version__)
+
+    parser.add_argument("--from", type=dateparse, dest="dateStart",
+        help="Start date for extraction, format '1990-12-13-22:33:45'. "+
+        "It is possible to be less precise and drop, seconds, minutes, hours or even day."+
+        " Default is one day ago",
+        default=dateStart)
+
+    parser.add_argument("--to", type=dateparse, dest="dateStop",
+        help="Stop date for extraction, format '1990-12-13-22:33:45'. It is possible to be less precise and drop, seconds, minutes, hours or even day."+
+        " Default is now.",
+        default=dateStop)
+
+    parser.add_argument("--DB", choices=["H", "T", "L"],
+        default="T", help="Database to extract from. HDB (H) or TDB (T), default: %(default)s")
+
+    parser.add_argument("--DBN", type=int, default=2,
+            help="Extractor device number, default: %(default)s")
+
+    parser.add_argument("--fileout", type=str, default="extracted_%s.npy"%datetime.datetime.now().strftime("%Y%m%d_%H%M%S"),
+            help="filename of the extraction destination. Default: %(default)s"),
+
+    parser.add_argument('--log', type=str, default="INFO",
+            help="Log level. Default: %(default)s.")
+
+
+    parser.add_argument('--filemode', action="store_true",
+            help="Set attribute to filemode."+
+            " Instead of specifying attributes, put a path to a file containing a list of attributes."+
+            " The file contains one attribute per line.")
+
+    parser.add_argument('attributes', type=str, nargs='+',
+                        help="List of attributes to extract. Full tango path.")
+
+    args = parser.parse_args()
+
+
+    #######################################################
+    # Configure logger
+
+    # Add a stream handler
+    s_handler = logging.StreamHandler()
+    s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s"))
+
+    # Set level according to command line attribute
+    s_handler.setLevel(level=getattr(logging, args.log.upper()))
+    logger.setLevel(level=getattr(logging, args.log.upper()))
+    logger.addHandler(s_handler)
+
+    logger.debug("Parsed arguments: %s"%args)
+
+    logger.info("Archive Extractor %s"%__version__)
+
+    #######################################################
+    # Filemode or not
+    if args.filemode:
+        logger.info("Filemode, openning file %s"%args.attributes[0])
+        # Read the file. Each line is an attribute
+        with open(args.attributes[0], "r") as fp:
+            attributes = fp.readlines()
+
+        logger.debug("Read lines : %s"%attributes)
+
+        # Clean end of line
+        for i_a in range(len(attributes)):
+            attributes[i_a] = attributes[i_a].rstrip()
+
+    else:
+        attributes = args.attributes
+
+    #######################################################
+    # Select Extractor
+    if args.DB == "L":
+        extractor = "archiving/extractor/%d"%(args.DBN)
+    else:
+        extractor = "archiving/%sDBExtractor/%d"%(args.DB, args.DBN)
+
+    #######################################################
+    # Prepare dictionnary for result
+    results = dict()
+
+    #######################################################
+    # Extract from database
+    logger.info("Extract from %s to %s."%(args.dateStart, args.dateStop))
+
+    for attr in attributes:
+        logger.info("Extracting attribute %s..."%attr)
+
+        for attempt in range(3):
+            try:
+                datevalue = query_ADB_BetweenDates(attr, args.dateStart, args.dateStop, extractor)
+
+                # Add to result dictionnary
+                results[attr] = datevalue
+
+            except ValueError as e:
+                logger.debug("ErrorMsg: %s"%e)
+                logger.warning("Failed to extract %s. Skipping..."%attr)
+            except (tango.CommunicationFailed, tango.DevFailed) as e:
+                # retry
+                logger.debug("ErrorMsg: %s"%e)
+                logger.warning("Failed to extract %s. Retry..."%attr)
+            break
+
+        else:
+            logger.error("The device %s might have crash.\n"%extractor+
+                    "You should check with Jive and probably restart with Astor.\n")
+
+        # Save all at each step
+        np.save(args.fileout, results)
+
+    logger.info("Extraction done, saved in file %s"%args.fileout)
+
+else:
+    # Name the logger after the module name
+    logger = logging.getLogger(__name__)