1515import linecache
1616import inspect
1717import subprocess
18- from copy import copy
1918import logging
2019
21- # TODO: provide alternative when multprocessing is not available
20+ # TODO: provide alternative when multiprocessing is not available
2221try :
2322 from multiprocessing import Process , Pipe
2423except ImportError :
3635
3736_TWO_20 = float (2 ** 20 )
3837
39- has_psutil = False
38+ if PY3 :
39+ import builtins
40+ else :
41+ import __builtin__ as builtins
4042
4143# .. get available packages ..
4244try :
4345 import psutil
4446 has_psutil = True
4547except ImportError :
46- pass
48+ has_psutil = False
4749
4850
4951def _get_memory (pid , timestamps = False , include_children = False ):
@@ -102,7 +104,7 @@ def _get_memory(pid, timestamps=False, include_children=False):
102104 if timestamps :
103105 return (- 1 , time .time ())
104106 else :
105- return - 1
107+ return - 1
106108 else :
107109 raise NotImplementedError ('The psutil module is required for non-unix '
108110 'platforms' )
@@ -121,29 +123,21 @@ def __init__(self, monitor_pid, interval, pipe, max_usage=False,
121123 self .max_usage = max_usage
122124 self .n_measurements = 1
123125
124- if "timestamps" in kw :
125- self .timestamps = kw ["timestamps" ]
126- del kw ["timestamps" ]
127- else :
128- self .timestamps = False
129- if "include_children" in kw :
130- self .include_children = kw ["include_children" ]
131- del kw ["include_children" ]
132- else :
133- self .include_children = False
126+ self .timestamps = kw .pop ("timestamps" , False )
127+ self .include_children = kw .pop ("include_children" , False )
128+
134129 # get baseline memory usage
135130 self .mem_usage = [
136131 _get_memory (self .monitor_pid , timestamps = self .timestamps ,
137132 include_children = self .include_children )]
138133 super (MemTimer , self ).__init__ (* args , ** kw )
139134
140-
141135 def run (self ):
142136 self .pipe .send (0 ) # we're ready
143137 stop = False
144138 while True :
145139 cur_mem = _get_memory (self .monitor_pid , timestamps = self .timestamps ,
146- include_children = self .include_children )
140+ include_children = self .include_children )
147141 if not self .max_usage :
148142 self .mem_usage .append (cur_mem )
149143 else :
@@ -223,7 +217,7 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
223217 # for a Python function wait until it finishes
224218 max_iter = float ('inf' )
225219
226- if hasattr (proc , '__call__' ):
220+ if callable (proc ):
227221 proc = (proc , (), {})
228222 if isinstance (proc , (list , tuple )):
229223 if len (proc ) == 1 :
@@ -238,7 +232,7 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
238232 while True :
239233 child_conn , parent_conn = Pipe () # this will store MemTimer's results
240234 p = MemTimer (os .getpid (), interval , child_conn , timestamps = timestamps ,
241- max_usage = max_usage , include_children = include_children )
235+ max_usage = max_usage , include_children = include_children )
242236 p .start ()
243237 parent_conn .recv () # wait until we start getting memory
244238 returned = f (* args , ** kw )
@@ -263,9 +257,9 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
263257 else :
264258 ret .append (mem_usage )
265259 else :
266- ret = max ([ ret ,
267- _get_memory (proc .pid ,
268- include_children = include_children )] )
260+ ret = max (ret ,
261+ _get_memory (proc .pid ,
262+ include_children = include_children ))
269263 time .sleep (interval )
270264 line_count += 1
271265 # flush every 50 lines. Make 'tail -f' usable on profile file
@@ -351,7 +345,7 @@ def __init__(self):
351345
352346 def __call__ (self , func = None , precision = None ):
353347 if func is not None :
354- if not hasattr (func , "__call__" ):
348+ if not callable (func ):
355349 raise ValueError ("Value must be callable" )
356350
357351 self .add_function (func )
@@ -380,7 +374,7 @@ def timestamp(self, name="<block>"):
380374 return _TimeStamperCM (timestamps )
381375
382376 def add_function (self , func ):
383- if not func in self .functions :
377+ if func not in self .functions :
384378 self .functions [func ] = []
385379
386380 def wrap_function (self , func ):
@@ -391,11 +385,10 @@ def f(*args, **kwds):
391385 timestamps = [_get_memory (os .getpid (), timestamps = True )]
392386 self .functions [func ].append (timestamps )
393387 try :
394- result = func (* args , ** kwds )
388+ return func (* args , ** kwds )
395389 finally :
396390 # end time
397391 timestamps .append (_get_memory (os .getpid (), timestamps = True ))
398- return result
399392 return f
400393
401394 def show_results (self , stream = None ):
@@ -459,10 +452,9 @@ def wrap_function(self, func):
459452 def f (* args , ** kwds ):
460453 self .enable_by_count ()
461454 try :
462- result = func (* args , ** kwds )
455+ return func (* args , ** kwds )
463456 finally :
464457 self .disable_by_count ()
465- return result
466458 return f
467459
468460 def run (self , cmd ):
@@ -521,8 +513,8 @@ def trace_max_mem(self, frame, event, arg):
521513 if event in ('line' , 'return' ) and frame .f_code in self .code_map :
522514 c = _get_memory (- 1 )
523515 if c >= self .max_mem :
524- t = ('Current memory {0:.2f} MiB exceeded the maximum '
525- '' . format ( c ) + ' of {0 :.2f} MiB\n ' .format (self .max_mem ))
516+ t = ('Current memory {0:.2f} MiB exceeded the '
517+ 'maximum of {1 :.2f} MiB\n ' .format (c , self .max_mem ))
526518 sys .stdout .write (t )
527519 sys .stdout .write ('Stepping into the debugger \n ' )
528520 frame .f_lineno -= 2
@@ -655,11 +647,8 @@ def mprun(self, parameter_s='', cell=None):
655647
656648 -c: If present, add the memory usage of any children process to the report.
657649 """
650+ from io import StringIO
658651 from memory_profiler import show_results , LineProfiler
659- try :
660- from StringIO import StringIO
661- except ImportError : # Python 3.x
662- from io import StringIO
663652
664653 # Local imports to avoid hard dependency.
665654 from distutils .version import LooseVersion
@@ -700,11 +689,6 @@ def mprun(self, parameter_s='', cell=None):
700689 profile (func )
701690
702691 # Add the profiler to the builtins for @profile.
703- if PY3 :
704- import builtins
705- else :
706- import __builtin__ as builtins
707-
708692 if 'profile' in builtins .__dict__ :
709693 had_profile = True
710694 old_profile = builtins .__dict__ ['profile' ]
@@ -714,14 +698,13 @@ def mprun(self, parameter_s='', cell=None):
714698 builtins .__dict__ ['profile' ] = profile
715699
716700 try :
717- try :
718- profile .runctx (arg_str , global_ns , local_ns )
719- message = ''
720- except SystemExit :
721- message = "*** SystemExit exception caught in code being profiled."
722- except KeyboardInterrupt :
723- message = ("*** KeyboardInterrupt exception caught in code being "
724- "profiled." )
701+ profile .runctx (arg_str , global_ns , local_ns )
702+ message = ''
703+ except SystemExit :
704+ message = "*** SystemExit exception caught in code being profiled."
705+ except KeyboardInterrupt :
706+ message = ("*** KeyboardInterrupt exception caught in code being "
707+ "profiled." )
725708 finally :
726709 if had_profile :
727710 builtins .__dict__ ['profile' ] = old_profile
@@ -888,6 +871,25 @@ def inner_wrapper(f):
888871 return profile (f , stream = stream , precision = precision )
889872 return inner_wrapper
890873
874+
875+ # Insert in the built-ins to have profile
876+ # globally defined (global variables is not enough
877+ # for all cases, e.g. a script that imports another
878+ # script where @profile is used)
879+ if PY3 :
880+ def exec_with_profiler (filename , profiler ):
881+ builtins .__dict__ ['profile' ] = profiler
882+ # shadow the profile decorator defined above
883+ ns = dict (_CLEAN_GLOBALS , profile = profiler )
884+ with open (filename ) as f :
885+ exec (compile (f .read (), filename , 'exec' ), ns , ns )
886+ else :
887+ def exec_with_profiler (filename , profiler ):
888+ builtins .__dict__ ['profile' ] = profiler
889+ ns = dict (_CLEAN_GLOBALS , profile = profiler )
890+ execfile (filename , ns , ns )
891+
892+
891893class LogFile (object ):
892894 """File-like object to log text using the `logging` module and the log report can be customised."""
893895
@@ -905,7 +907,7 @@ def __init__(self, name=None, reportIncrementFlag=False):
905907
906908 def write (self , msg , level = logging .INFO ):
907909 if self .reportIncrementFlag :
908- if "MiB" in msg and float (msg .split ("MiB" )[1 ].strip ())> 0 :
910+ if "MiB" in msg and float (msg .split ("MiB" )[1 ].strip ()) > 0 :
909911 self .logger .log (level , msg )
910912 elif msg .__contains__ ("Filename:" ) or msg .__contains__ ("Line Contents" ):
911913 self .logger .log (level , msg )
@@ -916,6 +918,7 @@ def flush(self):
916918 for handler in self .logger .handlers :
917919 handler .flush ()
918920
921+
919922if __name__ == '__main__' :
920923 from optparse import OptionParser
921924 parser = OptionParser (usage = _CMD_USAGE , version = __version__ )
@@ -947,24 +950,9 @@ def flush(self):
947950 prof = TimeStamper ()
948951 else :
949952 prof = LineProfiler (max_mem = options .max_mem )
950- __file__ = _find_script (args [0 ])
953+ script_filename = _find_script (args [0 ])
951954 try :
952- if not PY3 :
953- # we need to ovewrite the builtins to have profile
954- # globally defined (global variables is not enough
955- # for all cases, e.g. a script that imports another
956- # script where @profile is used)
957- import __builtin__
958- __builtin__ .__dict__ ['profile' ] = prof
959- ns = copy (_CLEAN_GLOBALS )
960- ns ['profile' ] = prof # shadow the profile decorator defined above
961- execfile (__file__ , ns , ns )
962- else :
963- import builtins
964- builtins .__dict__ ['profile' ] = prof
965- ns = copy (_CLEAN_GLOBALS )
966- ns ['profile' ] = prof # shadow the profile decorator defined above
967- exec (compile (open (__file__ ).read (), __file__ , 'exec' ), ns , ns )
955+ exec_with_profiler (script_filename , prof )
968956 finally :
969957 if options .out_filename is not None :
970958 out_file = open (options .out_filename , "a" )
0 commit comments