| """ |
| Helpers for logging. |
| |
| This module needs much love to become useful. |
| """ |
|
|
| |
| |
| |
|
|
| from __future__ import print_function |
|
|
| import logging |
| import os |
| import pprint |
| import shutil |
| import sys |
| import time |
|
|
| from .disk import mkdirp |
|
|
|
|
| def _squeeze_time(t): |
| """Remove .1s to the time under Windows: this is the time it take to |
| stat files. This is needed to make results similar to timings under |
| Unix, for tests |
| """ |
| if sys.platform.startswith("win"): |
| return max(0, t - 0.1) |
| else: |
| return t |
|
|
|
|
| def format_time(t): |
| t = _squeeze_time(t) |
| return "%.1fs, %.1fmin" % (t, t / 60.0) |
|
|
|
|
| def short_format_time(t): |
| t = _squeeze_time(t) |
| if t > 60: |
| return "%4.1fmin" % (t / 60.0) |
| else: |
| return " %5.1fs" % (t) |
|
|
|
|
| def pformat(obj, indent=0, depth=3): |
| if "numpy" in sys.modules: |
| import numpy as np |
|
|
| print_options = np.get_printoptions() |
| np.set_printoptions(precision=6, threshold=64, edgeitems=1) |
| else: |
| print_options = None |
| out = pprint.pformat(obj, depth=depth, indent=indent) |
| if print_options: |
| np.set_printoptions(**print_options) |
| return out |
|
|
|
|
| |
| |
| |
| class Logger(object): |
| """Base class for logging messages.""" |
|
|
| def __init__(self, depth=3, name=None): |
| """ |
| Parameters |
| ---------- |
| depth: int, optional |
| The depth of objects printed. |
| name: str, optional |
| The namespace to log to. If None, defaults to joblib. |
| """ |
| self.depth = depth |
| self._name = name if name else "joblib" |
|
|
| def warn(self, msg): |
| logging.getLogger(self._name).warning("[%s]: %s" % (self, msg)) |
|
|
| def info(self, msg): |
| logging.info("[%s]: %s" % (self, msg)) |
|
|
| def debug(self, msg): |
| |
| logging.getLogger(self._name).debug("[%s]: %s" % (self, msg)) |
|
|
| def format(self, obj, indent=0): |
| """Return the formatted representation of the object.""" |
| return pformat(obj, indent=indent, depth=self.depth) |
|
|
|
|
| |
| |
| |
| class PrintTime(object): |
| """Print and log messages while keeping track of time.""" |
|
|
| def __init__(self, logfile=None, logdir=None): |
| if logfile is not None and logdir is not None: |
| raise ValueError("Cannot specify both logfile and logdir") |
| |
| self.last_time = time.time() |
| self.start_time = self.last_time |
| if logdir is not None: |
| logfile = os.path.join(logdir, "joblib.log") |
| self.logfile = logfile |
| if logfile is not None: |
| mkdirp(os.path.dirname(logfile)) |
| if os.path.exists(logfile): |
| |
| for i in range(1, 9): |
| try: |
| shutil.move(logfile + ".%i" % i, logfile + ".%i" % (i + 1)) |
| except: |
| "No reason failing here" |
| |
| |
| try: |
| shutil.copy(logfile, logfile + ".1") |
| except: |
| "No reason failing here" |
| try: |
| with open(logfile, "w") as logfile: |
| logfile.write("\nLogging joblib python script\n") |
| logfile.write("\n---%s---\n" % time.ctime(self.last_time)) |
| except: |
| """ Multiprocessing writing to files can create race |
| conditions. Rather fail silently than crash the |
| computation. |
| """ |
| |
| |
|
|
| def __call__(self, msg="", total=False): |
| """Print the time elapsed between the last call and the current |
| call, with an optional message. |
| """ |
| if not total: |
| time_lapse = time.time() - self.last_time |
| full_msg = "%s: %s" % (msg, format_time(time_lapse)) |
| else: |
| |
| time_lapse = time.time() - self.start_time |
| full_msg = "%s: %.2fs, %.1f min" % (msg, time_lapse, time_lapse / 60) |
| print(full_msg, file=sys.stderr) |
| if self.logfile is not None: |
| try: |
| with open(self.logfile, "a") as f: |
| print(full_msg, file=f) |
| except: |
| """ Multiprocessing writing to files can create race |
| conditions. Rather fail silently than crash the |
| calculation. |
| """ |
| |
| |
| self.last_time = time.time() |
|
|