Skip to content

Commit 1828ac0

Browse files
committed
Merged in eteq/line_profiler (pull request rkern#4)
2 parents 00543af + c2a852b commit 1828ac0

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

line_profiler.py

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from cStringIO import StringIO
1111
except ImportError:
1212
from io import StringIO
13-
1413
import inspect
1514
import linecache
1615
import optparse
@@ -50,6 +49,7 @@ def is_generator(f):
5049
isgen = (f.__code__.co_flags & CO_GENERATOR) != 0
5150
return isgen
5251

52+
5353
class LineProfiler(CLineProfiler):
5454
""" A profiler that records the execution times of individual lines.
5555
"""
@@ -111,11 +111,11 @@ def dump_stats(self, filename):
111111
with open(filename, 'wb') as f:
112112
pickle.dump(lstats, f, pickle.HIGHEST_PROTOCOL)
113113

114-
def print_stats(self, stream=None):
114+
def print_stats(self, stream=None, stripzeros=False):
115115
""" Show the gathered statistics.
116116
"""
117117
lstats = self.get_stats()
118-
show_text(lstats.timings, lstats.unit, stream=stream)
118+
show_text(lstats.timings, lstats.unit, stream=stream, stripzeros=stripzeros)
119119

120120
def run(self, cmd):
121121
""" Profile a single executable statment in the main namespace.
@@ -143,24 +143,46 @@ def runcall(self, func, *args, **kw):
143143
finally:
144144
self.disable_by_count()
145145

146+
def add_module(self, mod):
147+
""" Add all the functions in a module and its classes.
148+
"""
149+
from inspect import isclass, isfunction
150+
151+
nfuncsadded = 0
152+
for item in mod.__dict__.values():
153+
if isclass(item):
154+
for k, v in item.__dict__.items():
155+
if isfunction(v):
156+
self.add_function(v)
157+
nfuncsadded += 1
158+
elif isfunction(item):
159+
self.add_function(item)
160+
nfuncsadded += 1
146161

147-
def show_func(filename, start_lineno, func_name, timings, unit, stream=None):
162+
return nfuncsadded
163+
164+
165+
def show_func(filename, start_lineno, func_name, timings, unit, stream=None, stripzeros=False):
148166
""" Show results for a single function.
149167
"""
150168
if stream is None:
151169
stream = sys.stdout
152170

153-
stream.write("File: %s\n" % filename)
154-
stream.write("Function: %s at line %s\n" % (func_name, start_lineno))
155171
template = '%6s %9s %12s %8s %8s %-s'
156172
d = {}
157173
total_time = 0.0
158174
linenos = []
159175
for lineno, nhits, time in timings:
160176
total_time += time
161177
linenos.append(lineno)
178+
179+
if stripzeros and total_time == 0:
180+
return
181+
162182
stream.write("Total time: %g s\n" % (total_time * unit))
163183
if os.path.exists(filename) or filename.startswith("<ipython-input-"):
184+
stream.write("File: %s\n" % filename)
185+
stream.write("Function: %s at line %s\n" % (func_name, start_lineno))
164186
if os.path.exists(filename):
165187
# Clear the cache to ensure that we get up-to-date results.
166188
linecache.clearcache()
@@ -195,15 +217,15 @@ def show_func(filename, start_lineno, func_name, timings, unit, stream=None):
195217
stream.write("\n")
196218
stream.write("\n")
197219

198-
def show_text(stats, unit, stream=None):
220+
def show_text(stats, unit, stream=None, stripzeros=False):
199221
""" Show text for the given timings.
200222
"""
201223
if stream is None:
202224
stream = sys.stdout
203225

204226
stream.write('Timer unit: %g s\n\n' % unit)
205227
for (fn, lineno, name), timings in sorted(stats.items()):
206-
show_func(fn, lineno, name, stats[fn, lineno, name], unit, stream=stream)
228+
show_func(fn, lineno, name, stats[fn, lineno, name], unit, stream=stream, stripzeros=stripzeros)
207229

208230
# A %lprun magic for IPython.
209231
def magic_lprun(self, parameter_s=''):
@@ -228,7 +250,9 @@ def magic_lprun(self, parameter_s=''):
228250
in the interpreter at the In[] prompt or via %run currently cannot be
229251
displayed. Write these functions out to a separate file and import them.
230252
231-
One or more -f options are required to get any useful results.
253+
-m <module>: Get all the functions/methods in a module
254+
255+
One or more -f or -m options are required to get any useful results.
232256
233257
-D <filename>: dump the raw statistics out to a pickle file on disk. The
234258
usual extension for this is ".lprof". These statistics may be viewed later
@@ -238,6 +262,8 @@ def magic_lprun(self, parameter_s=''):
238262
out to a text file.
239263
240264
-r: return the LineProfiler object after it has completed profiling.
265+
266+
-s: strip out all entries from the print-out that have zeros.
241267
"""
242268
# Local imports to avoid hard dependency.
243269
from distutils.version import LooseVersion
@@ -253,9 +279,9 @@ def magic_lprun(self, parameter_s=''):
253279
from IPython.core.error import UsageError
254280

255281
# Escape quote markers.
256-
opts_def = Struct(D=[''], T=[''], f=[])
282+
opts_def = Struct(D=[''], T=[''], f=[], m=[])
257283
parameter_s = parameter_s.replace('"', r'\"').replace("'", r"\'")
258-
opts, arg_str = self.parse_options(parameter_s, 'rf:D:T:', list_all=True)
284+
opts, arg_str = self.parse_options(parameter_s, 'rsf:m:D:T:', list_all=True)
259285
opts.merge(opts_def)
260286

261287
global_ns = self.shell.user_global_ns
@@ -272,6 +298,15 @@ def magic_lprun(self, parameter_s=''):
272298

273299
profile = LineProfiler(*funcs)
274300

301+
# Get the modules, too
302+
for modname in opts.m:
303+
try:
304+
mod = __import__(modname, fromlist=[''])
305+
profile.add_module(mod)
306+
except Exception as e:
307+
raise UsageError('Could not find module %r.\n%s: %s' % (name,
308+
e.__class__.__name__, e))
309+
275310
# Add the profiler to the builtins for @profile.
276311
if PY3:
277312
import builtins
@@ -301,7 +336,7 @@ def magic_lprun(self, parameter_s=''):
301336

302337
# Trap text output.
303338
stdout_trap = StringIO()
304-
profile.print_stats(stdout_trap)
339+
profile.print_stats(stdout_trap, stripzeros='s' in opts)
305340
output = stdout_trap.getvalue()
306341
output = output.rstrip()
307342

0 commit comments

Comments
 (0)