Skip to content

Commit c2a852b

Browse files
committed
Added stripzeros and add_module to support ipython -m and -s
1 parent af6c21c commit c2a852b

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

line_profiler.py

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
def is_generator(f):
1717
""" Return True if a function is a generator.
1818
"""
19-
isgen = (f.func_code.co_flags & CO_GENERATOR) != 0
19+
isgen = (f.func_code.co_flags & CO_GENERATOR) != 0
2020
return isgen
2121

2222
# Code to exec inside of LineProfiler.__call__ to support PEP-342-style
@@ -106,11 +106,12 @@ def dump_stats(self, filename):
106106
finally:
107107
f.close()
108108

109-
def print_stats(self, stream=None):
109+
def print_stats(self, stream=None, stripzeros=False):
110110
""" Show the gathered statistics.
111111
"""
112112
lstats = self.get_stats()
113-
show_text(lstats.timings, lstats.unit, stream=stream)
113+
114+
show_text(lstats.timings, lstats.unit, stream=stream, stripzeros=stripzeros)
114115

115116
def run(self, cmd):
116117
""" Profile a single executable statment in the main namespace.
@@ -138,21 +139,44 @@ def runcall(self, func, *args, **kw):
138139
finally:
139140
self.disable_by_count()
140141

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

142-
def show_func(filename, start_lineno, func_name, timings, unit, stream=None):
161+
def show_func(filename, start_lineno, func_name, timings, unit, stream=None, stripzeros=False):
143162
""" Show results for a single function.
144163
"""
145164
if stream is None:
146165
stream = sys.stdout
147-
print >>stream, "File: %s" % filename
148-
print >>stream, "Function: %s at line %s" % (func_name, start_lineno)
149166
template = '%6s %9s %12s %8s %8s %-s'
150167
d = {}
151168
total_time = 0.0
152169
linenos = []
153170
for lineno, nhits, time in timings:
154171
total_time += time
155172
linenos.append(lineno)
173+
174+
if stripzeros and total_time == 0:
175+
return
176+
177+
print >>stream, "File: %s" % filename
178+
print >>stream, "Function: %s at line %s" % (func_name, start_lineno)
179+
156180
print >>stream, "Total time: %g s" % (total_time * unit)
157181
if not os.path.exists(filename):
158182
print >>stream, ""
@@ -173,7 +197,7 @@ def show_func(filename, start_lineno, func_name, timings, unit, stream=None):
173197
'%5.1f' % (100*time / total_time))
174198
linenos = range(start_lineno, start_lineno + len(sublines))
175199
empty = ('', '', '', '')
176-
header = template % ('Line #', 'Hits', 'Time', 'Per Hit', '% Time',
200+
header = template % ('Line #', 'Hits', 'Time', 'Per Hit', '% Time',
177201
'Line Contents')
178202
print >>stream, ""
179203
print >>stream, header
@@ -184,15 +208,15 @@ def show_func(filename, start_lineno, func_name, timings, unit, stream=None):
184208
line.rstrip('\n').rstrip('\r'))
185209
print >>stream, ""
186210

187-
def show_text(stats, unit, stream=None):
211+
def show_text(stats, unit, stream=None, stripzeros=False):
188212
""" Show text for the given timings.
189213
"""
190214
if stream is None:
191215
stream = sys.stdout
192216
print >>stream, 'Timer unit: %g s' % unit
193217
print >>stream, ''
194218
for (fn, lineno, name), timings in sorted(stats.items()):
195-
show_func(fn, lineno, name, stats[fn, lineno, name], unit, stream=stream)
219+
show_func(fn, lineno, name, stats[fn, lineno, name], unit, stream=stream, stripzeros=stripzeros)
196220

197221
# A %lprun magic for IPython.
198222
def magic_lprun(self, parameter_s=''):
@@ -208,7 +232,7 @@ def magic_lprun(self, parameter_s=''):
208232
pager once the statement has completed.
209233
210234
Options:
211-
235+
212236
-f <function>: LineProfiler only profiles functions and methods it is told
213237
to profile. This option tells the profiler about these functions. Multiple
214238
-f options may be used. The argument may be any expression that gives
@@ -217,7 +241,9 @@ def magic_lprun(self, parameter_s=''):
217241
in the interpreter at the In[] prompt or via %run currently cannot be
218242
displayed. Write these functions out to a separate file and import them.
219243
220-
One or more -f options are required to get any useful results.
244+
-m <module>: Get all the functions/methods in a module
245+
246+
One or more -f or -m options are required to get any useful results.
221247
222248
-D <filename>: dump the raw statistics out to a pickle file on disk. The
223249
usual extension for this is ".lprof". These statistics may be viewed later
@@ -227,6 +253,8 @@ def magic_lprun(self, parameter_s=''):
227253
out to a text file.
228254
229255
-r: return the LineProfiler object after it has completed profiling.
256+
257+
-s: strip out all entries from the print-out that have zeros.
230258
"""
231259
# Local imports to avoid hard dependency.
232260
from distutils.version import LooseVersion
@@ -242,9 +270,9 @@ def magic_lprun(self, parameter_s=''):
242270
from IPython.core.error import UsageError
243271

244272
# Escape quote markers.
245-
opts_def = Struct(D=[''], T=[''], f=[])
273+
opts_def = Struct(D=[''], T=[''], f=[], m=[])
246274
parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
247-
opts, arg_str = self.parse_options(parameter_s, 'rf:D:T:', list_all=True)
275+
opts, arg_str = self.parse_options(parameter_s, 'rsf:m:D:T:', list_all=True)
248276
opts.merge(opts_def)
249277

250278
global_ns = self.shell.user_global_ns
@@ -256,11 +284,20 @@ def magic_lprun(self, parameter_s=''):
256284
try:
257285
funcs.append(eval(name, global_ns, local_ns))
258286
except Exception, e:
259-
raise UsageError('Could not find function %r.\n%s: %s' % (name,
287+
raise UsageError('Could not find function %r.\n%s: %s' % (name,
260288
e.__class__.__name__, e))
261289

262290
profile = LineProfiler(*funcs)
263291

292+
#get the modules, too
293+
for modname in opts.m:
294+
try:
295+
mod = __import__(modname, fromlist=[''])
296+
profile.add_module(mod)
297+
except Exception, e:
298+
raise UsageError('Could not find module %r.\n%s: %s' % (name,
299+
e.__class__.__name__, e))
300+
264301
# Add the profiler to the builtins for @profile.
265302
import __builtin__
266303
if 'profile' in __builtin__.__dict__:
@@ -286,7 +323,7 @@ def magic_lprun(self, parameter_s=''):
286323

287324
# Trap text output.
288325
stdout_trap = StringIO()
289-
profile.print_stats(stdout_trap)
326+
profile.print_stats(stdout_trap, stripzeros=opts.has_key('s'))
290327
output = stdout_trap.getvalue()
291328
output = output.rstrip()
292329

0 commit comments

Comments
 (0)