[Python-ideas] Allow Profile() to be used as a context manager
Robert Kern
robert.kern at gmail.com
Wed Jan 25 12:37:46 CET 2012
On 1/25/12 8:19 AM, Yuval Greenfield wrote:
> On Wed, Jan 25, 2012 at 8:36 AM, David Townshend
> <aquavitae69 at gmail.com
> <mailto:aquavitae69 at gmail.com>> wrote:
>
> [...]
> Any major objections to this?
>
>
>
> At first this sounded like a good idea but 2 things pop to mind:
>
> 1. How does one get the pstat profiling output from the context manager? Will
> printing out the results be the only option?
> 2. Usually when I profile I don't want to touch the code at all so eventually
> if I'll use this context manager it'll be more akin to
>
>
> with profile.Profiler():
> main()
>
> Which isn't much of a win over
>
> profile.run('main()')
>
>
> Now if you're talking about a reentrant profiler, that's interesting:
>
> profiler = profile.Profiler()
>
> while is_working:
> with profiler:
> do_hard_task()
> do_a_hard_but_i_dont_care_now_task()
>
> with profiler:
> do_a_diff_hard_task()
>
>
> and then I can call whatever method is there to get the pstat. If this is the
> vision then it sounds awesome.
<shameless-advertisement>
You may want to take a look at my kernprof script mentioned elsewhere in the thread:
http://packages.python.org/line_profiler/
http://pypi.python.org/pypi/line_profiler/
Besides adding the context manager to Profile, it is a generic "runner" script
that will run your script under the profiler and dump the results to a file. In
the normal use case of profiling the entire script, you don't have to modify
your code at all:
[line_profiler]$ kernprof.py -v pystone.py
Pystone(1.1) time for 50000 passes = 0.918603
This machine benchmarks at 54430.5 pystones/second
Wrote profile results to pystone.py.prof
1100070 function calls in 0.929 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.929 0.929 <string>:1(<module>)
50000 0.140 0.000 0.322 0.000 pystone.py:137(Proc1)
50000 0.029 0.000 0.029 0.000 pystone.py:153(Proc2)
50000 0.036 0.000 0.048 0.000 pystone.py:164(Proc3)
50000 0.015 0.000 0.015 0.000 pystone.py:174(Proc4)
50000 0.013 0.000 0.013 0.000 pystone.py:181(Proc5)
50000 0.033 0.000 0.043 0.000 pystone.py:188(Proc6)
150000 0.034 0.000 0.034 0.000 pystone.py:207(Proc7)
50000 0.100 0.000 0.126 0.000 pystone.py:212(Proc8)
150000 0.035 0.000 0.035 0.000 pystone.py:225(Func1)
...
But if you do want to use the context manager or the decorator, then there is a
flag to the script that injects the Profile instance into the builtins. Then you
can use "@profile" or "with profile:" to only enable the profiler at certain
points (and multiple points as in your use case above). These are the only
modifications you need to make. The stats dumping is handled by kernprof.
[line_profiler]$ grin -A10 '@profile' pystone.py
pystone.py:
164 : @profile
165 + def Proc3(PtrParOut):
166 + global IntGlob
167 +
168 + if PtrGlb is not None:
169 + PtrParOut = PtrGlb.PtrComp
170 + else:
171 + IntGlob = 100
172 + PtrGlb.IntComp = Proc7(10, IntGlob)
173 + return PtrParOut
174 +
182 : @profile
183 + def Proc5():
184 + global Char1Glob
185 + global BoolGlob
186 +
187 + Char1Glob = 'A'
188 + BoolGlob = FALSE
189 +
190 + def Proc6(EnumParIn):
191 + EnumParOut = EnumParIn
192 + if not Func3(EnumParIn):
[line_profiler]$ kernprof.py -v --builtin pystone.py
Pystone(1.1) time for 50000 passes = 1.08921
This machine benchmarks at 45904.8 pystones/second
Wrote profile results to pystone.py.prof
350000 function calls in 0.192 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
100000 0.116 0.000 0.123 0.000 kernprof.py:73(disable_by_count)
50000 0.042 0.000 0.055 0.000 pystone.py:164(Proc3)
50000 0.013 0.000 0.013 0.000 pystone.py:182(Proc5)
50000 0.013 0.000 0.013 0.000 pystone.py:209(Proc7)
100000 0.007 0.000 0.007 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
</shameless-advertisement>
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
More information about the Python-ideas
mailing list