33# .. we'll use this to pass it to the child script ..
44_CLEAN_GLOBALS = globals ().copy ()
55
6- __version__ = '0.50 .0'
6+ __version__ = '0.55 .0'
77
88_CMD_USAGE = "python -m memory_profiler script_file.py"
99
10- import time
11- import sys
10+ from functools import wraps
11+ import inspect
12+ import linecache
13+ import logging
1214import os
1315import pdb
14- import warnings
15- import linecache
16- import inspect
1716import subprocess
18- import logging
17+ import sys
18+ import time
1919import traceback
20+ import warnings
21+
2022if sys .platform == "win32" :
2123 # any value except signal.CTRL_C_EVENT and signal.CTRL_BREAK_EVENT
2224 # can be used to kill a process unconditionally in Windows
4749if PY2 :
4850 import __builtin__ as builtins
4951 to_str = lambda x : x
52+ from future_builtins import filter
5053else :
5154 import builtins
5255 to_str = lambda x : str (x )
@@ -403,13 +406,13 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
403406
404407 # Write children to the stream file
405408 if multiprocess :
406- for idx , chldmem in enumerate (_get_child_memory (proc . pid )):
409+ for idx , chldmem in enumerate (_get_child_memory (proc )):
407410 stream .write ("CHLD {0} {1:.6f} {2:.4f}\n " .format (idx , chldmem , time .time ()))
408411 else :
409412 # Create a nested list with the child memory
410413 if multiprocess :
411414 mem_usage = [mem_usage ]
412- for chldmem in _get_child_memory (proc . pid ):
415+ for chldmem in _get_child_memory (proc ):
413416 mem_usage .append (chldmem )
414417
415418 # Append the memory usage to the return value
@@ -592,9 +595,7 @@ def trace(self, code, lineno, prev_lineno):
592595
593596 prev_line_value = self [code ].get (prev_lineno , None ) if prev_lineno else None
594597 prev_line_memory = prev_line_value [1 ] if prev_line_value else 0
595- #inc = (memory-prev_line_memory)
596- #print('trace lineno=%(lineno)s prev_lineno=%(prev_lineno)s mem=%(memory)s prev_inc=%(previous_inc)s inc=%(inc)s' % locals())
597- self [code ][lineno ] = (previous_inc + (memory - prev_line_memory ), max (memory , previous_memory ))
598+ self [code ][lineno ] = (max (previous_inc , memory - prev_line_memory ), max (memory , previous_memory ))
598599
599600 def items (self ):
600601 """Iterate on the toplevel code blocks."""
@@ -1065,6 +1066,7 @@ def profile(func=None, stream=None, precision=1, backend='psutil'):
10651066 if not tracemalloc .is_tracing ():
10661067 tracemalloc .start ()
10671068 if func is not None :
1069+ @wraps (func )
10681070 def wrapper (* args , ** kwargs ):
10691071 prof = LineProfiler (backend = backend )
10701072 val = prof (func )(* args , ** kwargs )
@@ -1111,23 +1113,35 @@ def choose_backend(new_backend=None):
11111113# globally defined (global variables is not enough
11121114# for all cases, e.g. a script that imports another
11131115# script where @profile is used)
1114- if PY2 :
1115- def exec_with_profiler (filename , profiler , backend ):
1116- builtins .__dict__ ['profile' ] = profiler
1117- ns = dict (_CLEAN_GLOBALS , profile = profiler )
1118- choose_backend (backend )
1119- execfile (filename , ns , ns )
1120- else :
1121- def exec_with_profiler (filename , profiler , backend ):
1122- _backend = choose_backend (backend )
1116+ def exec_with_profiler (filename , profiler , backend , passed_args = []):
1117+ from runpy import run_module
1118+ builtins .__dict__ ['profile' ] = profiler
1119+ ns = dict (_CLEAN_GLOBALS , profile = profiler )
1120+ _backend = choose_backend (backend )
1121+ sys .argv = [filename ] + passed_args
1122+ try :
1123+ if _backend == 'tracemalloc' and has_tracemalloc :
1124+ tracemalloc .start ()
1125+ with open (filename ) as f :
1126+ exec (compile (f .read (), filename , 'exec' ), ns , ns )
1127+ finally :
1128+ if has_tracemalloc and tracemalloc .is_tracing ():
1129+ tracemalloc .stop ()
1130+
1131+
1132+ def run_module_with_profiler (module , profiler , backend , passed_args = []):
1133+ from runpy import run_module
1134+ builtins .__dict__ ['profile' ] = profiler
1135+ ns = dict (_CLEAN_GLOBALS , profile = profiler )
1136+ _backend = choose_backend (backend )
1137+ sys .argv = [module ] + passed_args
1138+ if PY2 :
1139+ run_module (module , run_name = "__main__" , init_globals = ns )
1140+ else :
11231141 if _backend == 'tracemalloc' and has_tracemalloc :
11241142 tracemalloc .start ()
1125- builtins .__dict__ ['profile' ] = profiler
1126- # shadow the profile decorator defined above
1127- ns = dict (_CLEAN_GLOBALS , profile = profiler )
11281143 try :
1129- with open (filename ) as f :
1130- exec (compile (f .read (), filename , 'exec' ), ns , ns )
1144+ run_module (module , run_name = "__main__" , init_globals = ns )
11311145 finally :
11321146 if has_tracemalloc and tracemalloc .is_tracing ():
11331147 tracemalloc .stop ()
@@ -1166,7 +1180,7 @@ def flush(self):
11661180
11671181
11681182if __name__ == '__main__' :
1169- from argparse import ArgumentParser
1183+ from argparse import ArgumentParser , REMAINDER
11701184
11711185 parser = ArgumentParser (usage = _CMD_USAGE )
11721186 parser .add_argument ('--version' , action = 'version' , version = __version__ )
@@ -1189,18 +1203,28 @@ def flush(self):
11891203 choices = ['tracemalloc' , 'psutil' , 'posix' ], default = 'psutil' ,
11901204 help = 'backend using for getting memory info '
11911205 '(one of the {tracemalloc, psutil, posix})' )
1192- parser .add_argument ('script' , help = 'script file run on memory_profiler' )
1206+ parser .add_argument ("program" , nargs = REMAINDER ,
1207+ help = 'python script or module followed by command line arguements to run' )
11931208 args = parser .parse_args ()
11941209
1195- script_filename = _find_script (args .script )
1210+ if len (args .program ) == 0 :
1211+ print ("A program to run must be provided. Use -h for help" )
1212+ sys .exit (1 )
1213+
1214+ target = args .program [0 ]
1215+ script_args = args .program [1 :]
11961216 _backend = choose_backend (args .backend )
11971217 if args .timestamp :
11981218 prof = TimeStamper (_backend )
11991219 else :
12001220 prof = LineProfiler (max_mem = args .max_mem , backend = _backend )
12011221
12021222 try :
1203- exec_with_profiler (script_filename , prof , args .backend )
1223+ if args .program [0 ].endswith ('.py' ):
1224+ script_filename = _find_script (args .program [0 ])
1225+ exec_with_profiler (script_filename , prof , args .backend , script_args )
1226+ else :
1227+ run_module_with_profiler (target , prof , args .backend , script_args )
12041228 finally :
12051229 if args .out_filename is not None :
12061230 out_file = open (args .out_filename , "a" )
0 commit comments