Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/joblib/logger.py: 28%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

80 statements  

1""" 

2Helpers for logging. 

3 

4This module needs much love to become useful. 

5""" 

6 

7# Author: Gael Varoquaux <gael dot varoquaux at normalesup dot org> 

8# Copyright (c) 2008 Gael Varoquaux 

9# License: BSD Style, 3 clauses. 

10 

11from __future__ import print_function 

12 

13import logging 

14import os 

15import pprint 

16import shutil 

17import sys 

18import time 

19 

20from .disk import mkdirp 

21 

22 

23def _squeeze_time(t): 

24 """Remove .1s to the time under Windows: this is the time it take to 

25 stat files. This is needed to make results similar to timings under 

26 Unix, for tests 

27 """ 

28 if sys.platform.startswith("win"): 

29 return max(0, t - 0.1) 

30 else: 

31 return t 

32 

33 

34def format_time(t): 

35 """Format a duration in seconds as a human-readable string. 

36 

37 Returns both seconds and minutes, e.g. ``'12.3s, 0.2min'``. 

38 

39 Parameters 

40 ---------- 

41 t : float 

42 Duration in seconds. 

43 

44 Returns 

45 ------- 

46 str 

47 Formatted string showing the duration in seconds and minutes. 

48 """ 

49 t = _squeeze_time(t) 

50 return "%.1fs, %.1fmin" % (t, t / 60.0) 

51 

52 

53def short_format_time(t): 

54 """Format a duration in seconds as a compact human-readable string. 

55 

56 Returns minutes for durations over 60 seconds, otherwise seconds. 

57 

58 Parameters 

59 ---------- 

60 t : float 

61 Duration in seconds. 

62 

63 Returns 

64 ------- 

65 str 

66 Formatted string: ``' 42.0s'`` for short durations or 

67 ``' 1.2min'`` for longer ones. 

68 """ 

69 t = _squeeze_time(t) 

70 if t > 60: 

71 return "%4.1fmin" % (t / 60.0) 

72 else: 

73 return " %5.1fs" % (t) 

74 

75 

76def pformat(obj, indent=0, depth=3): 

77 """Return a pretty-printed string representation of an object. 

78 

79 Uses :func:`pprint.pformat` with numpy print options temporarily 

80 reduced to keep output concise when numpy is available. 

81 

82 Parameters 

83 ---------- 

84 obj : object 

85 The object to format. 

86 indent : int, optional 

87 Indentation level passed to :func:`pprint.pformat`. Default is 0. 

88 depth : int, optional 

89 Maximum nesting depth passed to :func:`pprint.pformat`. Default is 3. 

90 

91 Returns 

92 ------- 

93 str 

94 Pretty-printed string representation of ``obj``. 

95 """ 

96 if "numpy" in sys.modules: 

97 import numpy as np 

98 

99 print_options = np.get_printoptions() 

100 np.set_printoptions(precision=6, threshold=64, edgeitems=1) 

101 else: 

102 print_options = None 

103 out = pprint.pformat(obj, depth=depth, indent=indent) 

104 if print_options: 

105 np.set_printoptions(**print_options) 

106 return out 

107 

108 

109############################################################################### 

110# class `Logger` 

111############################################################################### 

112class Logger(object): 

113 """Base class for logging messages.""" 

114 

115 def __init__(self, depth=3, name=None): 

116 """ 

117 Parameters 

118 ---------- 

119 depth: int, optional 

120 The depth of objects printed. 

121 name: str, optional 

122 The namespace to log to. If None, defaults to joblib. 

123 """ 

124 self.depth = depth 

125 self._name = name if name else "joblib" 

126 

127 def warn(self, msg): 

128 logging.getLogger(self._name).warning("[%s]: %s" % (self, msg)) 

129 

130 def info(self, msg): 

131 logging.info("[%s]: %s" % (self, msg)) 

132 

133 def debug(self, msg): 

134 # XXX: This conflicts with the debug flag used in children class 

135 logging.getLogger(self._name).debug("[%s]: %s" % (self, msg)) 

136 

137 def format(self, obj, indent=0): 

138 """Return the formatted representation of the object.""" 

139 return pformat(obj, indent=indent, depth=self.depth) 

140 

141 

142############################################################################### 

143# class `PrintTime` 

144############################################################################### 

145class PrintTime(object): 

146 """Print and log messages while keeping track of time.""" 

147 

148 def __init__(self, logfile=None, logdir=None): 

149 if logfile is not None and logdir is not None: 

150 raise ValueError("Cannot specify both logfile and logdir") 

151 # XXX: Need argument docstring 

152 self.last_time = time.time() 

153 self.start_time = self.last_time 

154 if logdir is not None: 

155 logfile = os.path.join(logdir, "joblib.log") 

156 self.logfile = logfile 

157 if logfile is not None: 

158 mkdirp(os.path.dirname(logfile)) 

159 if os.path.exists(logfile): 

160 # Rotate the logs 

161 for i in range(1, 9): 

162 try: 

163 shutil.move(logfile + ".%i" % i, logfile + ".%i" % (i + 1)) 

164 except: # noqa: E722 

165 "No reason failing here" 

166 # Use a copy rather than a move, so that a process 

167 # monitoring this file does not get lost. 

168 try: 

169 shutil.copy(logfile, logfile + ".1") 

170 except: # noqa: E722 

171 "No reason failing here" 

172 try: 

173 with open(logfile, "w") as logfile: 

174 logfile.write("\nLogging joblib python script\n") 

175 logfile.write("\n---%s---\n" % time.ctime(self.last_time)) 

176 except: # noqa: E722 

177 """ Multiprocessing writing to files can create race 

178 conditions. Rather fail silently than crash the 

179 computation. 

180 """ 

181 # XXX: We actually need a debug flag to disable this 

182 # silent failure. 

183 

184 def __call__(self, msg="", total=False): 

185 """Print the time elapsed between the last call and the current 

186 call, with an optional message. 

187 """ 

188 if not total: 

189 time_lapse = time.time() - self.last_time 

190 full_msg = "%s: %s" % (msg, format_time(time_lapse)) 

191 else: 

192 # FIXME: Too much logic duplicated 

193 time_lapse = time.time() - self.start_time 

194 full_msg = "%s: %.2fs, %.1f min" % (msg, time_lapse, time_lapse / 60) 

195 print(full_msg, file=sys.stderr) 

196 if self.logfile is not None: 

197 try: 

198 with open(self.logfile, "a") as f: 

199 print(full_msg, file=f) 

200 except: # noqa: E722 

201 """ Multiprocessing writing to files can create race 

202 conditions. Rather fail silently than crash the 

203 calculation. 

204 """ 

205 # XXX: We actually need a debug flag to disable this 

206 # silent failure. 

207 self.last_time = time.time()