Skip to content

Commit 00543af

Browse files
committed
Merged in kmike/line_profiler (pull request rkern#2)
2 parents 819fb22 + 64f8554 commit 00543af

File tree

4 files changed

+166
-149
lines changed

4 files changed

+166
-149
lines changed

_line_profiler.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ cdef class LineProfiler:
125125
""" Record line profiling information for the given Python function.
126126
"""
127127
try:
128-
code = func.func_code
128+
code = func.__code__
129129
except AttributeError:
130130
import warnings
131131
warnings.warn("Could not extract a code object for the object %r" % (func,))

kernprof.py

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import sys
99

1010

11-
# Guard the import of cProfile such that 2.4 people without lsprof can still use
12-
# this script.
11+
# Guard the import of cProfile such that 3.x people
12+
# without lsprof can still use this script.
1313
try:
1414
from cProfile import Profile
1515
except ImportError:
@@ -19,40 +19,29 @@
1919
from profile import Profile
2020

2121

22+
# Python 3.x compatibility utils: execfile
23+
# ========================================
24+
try:
25+
execfile
26+
except NameError:
27+
# Python 3.x doesn't have 'execfile' builtin
28+
import builtins
29+
exec_ = getattr(builtins, "exec")
30+
31+
def execfile(filename, globals=None, locals=None):
32+
with open(filename) as f:
33+
exec_(compile(f.read(), filename, 'exec'), globals, locals)
34+
# =====================================
35+
36+
37+
2238
CO_GENERATOR = 0x0020
2339
def is_generator(f):
2440
""" Return True if a function is a generator.
2541
"""
26-
isgen = (f.func_code.co_flags & CO_GENERATOR) != 0
42+
isgen = (f.__code__.co_flags & CO_GENERATOR) != 0
2743
return isgen
2844

29-
# FIXME: refactor this stuff so that both LineProfiler and ContextualProfile can
30-
# use the same implementation.
31-
# Code to exec inside of ContextualProfile.__call__ to support PEP-342-style
32-
# generators in Python 2.5+.
33-
pep342_gen_wrapper = '''
34-
def wrap_generator(self, func):
35-
""" Wrap a generator to profile it.
36-
"""
37-
def f(*args, **kwds):
38-
g = func(*args, **kwds)
39-
# The first iterate will not be a .send()
40-
self.enable_by_count()
41-
try:
42-
item = g.next()
43-
finally:
44-
self.disable_by_count()
45-
input = (yield item)
46-
# But any following one might be.
47-
while True:
48-
self.enable_by_count()
49-
try:
50-
item = g.send(input)
51-
finally:
52-
self.disable_by_count()
53-
input = (yield item)
54-
return f
55-
'''
5645

5746
class ContextualProfile(Profile):
5847
""" A subclass of Profile that adds a context manager for Python
@@ -95,24 +84,29 @@ def __call__(self, func):
9584
f.__dict__.update(getattr(func, '__dict__', {}))
9685
return f
9786

98-
if sys.version_info[:2] >= (2,5):
99-
# Delay compilation because the syntax is not compatible with older
100-
# Python versions.
101-
exec pep342_gen_wrapper
102-
else:
103-
def wrap_generator(self, func):
104-
""" Wrap a generator to profile it.
105-
"""
106-
def f(*args, **kwds):
107-
g = func(*args, **kwds)
108-
while True:
109-
self.enable_by_count()
110-
try:
111-
item = g.next()
112-
finally:
113-
self.disable_by_count()
114-
yield item
115-
return f
87+
# FIXME: refactor this stuff so that both LineProfiler and
88+
# ContextualProfile can use the same implementation.
89+
def wrap_generator(self, func):
90+
""" Wrap a generator to profile it.
91+
"""
92+
def f(*args, **kwds):
93+
g = func(*args, **kwds)
94+
# The first iterate will not be a .send()
95+
self.enable_by_count()
96+
try:
97+
item = next(g)
98+
finally:
99+
self.disable_by_count()
100+
input = (yield item)
101+
# But any following one might be.
102+
while True:
103+
self.enable_by_count()
104+
try:
105+
item = g.send(input)
106+
finally:
107+
self.disable_by_count()
108+
input = (yield item)
109+
return f
116110

117111
def wrap_function(self, func):
118112
""" Wrap a function to profile it.
@@ -148,9 +142,10 @@ def find_script(script_name):
148142
if os.path.isfile(fn):
149143
return fn
150144

151-
print >>sys.stderr, 'Could not find script %s' % script_name
145+
sys.stderr.write('Could not find script %s\n' % script_name)
152146
raise SystemExit(1)
153147

148+
154149
def main(args):
155150
usage = "%prog [-s setupfile] [-o output_file_path] scriptfile [arg] ..."
156151
parser = optparse.OptionParser(usage=usage, version="%prog 1.0b2")
@@ -204,8 +199,11 @@ def main(args):
204199
else:
205200
prof = ContextualProfile()
206201
if options.builtin:
207-
import __builtin__
208-
__builtin__.__dict__['profile'] = prof
202+
try:
203+
import builtins
204+
except ImportError: # Python 2.x
205+
import __builtin__ as builtins
206+
builtins.__dict__['profile'] = prof
209207

210208
script_file = find_script(sys.argv[0])
211209
__file__ = script_file
@@ -216,16 +214,17 @@ def main(args):
216214

217215
try:
218216
try:
217+
execfile_ = execfile
219218
ns = locals()
220219
if options.builtin:
221220
execfile(script_file, ns, ns)
222221
else:
223-
prof.runctx('execfile(%r)' % (script_file,), ns, ns)
222+
prof.runctx('execfile_(%r, globals())' % (script_file,), ns, ns)
224223
except (KeyboardInterrupt, SystemExit):
225224
pass
226225
finally:
227226
prof.dump_stats(options.outfile)
228-
print 'Wrote profile results to %s' % options.outfile
227+
print('Wrote profile results to %s' % options.outfile)
229228
if options.view:
230229
prof.print_stats()
231230

0 commit comments

Comments
 (0)