Skip to content

Commit ca55ac7

Browse files
committed
Allow passing args to profiled script or module
Also attempted to clarify usage Made to address #179
1 parent 5106293 commit ca55ac7

2 files changed

Lines changed: 49 additions & 19 deletions

File tree

memory_profiler.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,20 +1113,17 @@ def choose_backend(new_backend=None):
11131113
# globally defined (global variables is not enough
11141114
# for all cases, e.g. a script that imports another
11151115
# script where @profile is used)
1116-
if PY2:
1117-
def exec_with_profiler(filename, profiler, backend):
1118-
builtins.__dict__['profile'] = profiler
1119-
ns = dict(_CLEAN_GLOBALS, profile=profiler)
1120-
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+
if PY2:
11211123
execfile(filename, ns, ns)
1122-
else:
1123-
def exec_with_profiler(filename, profiler, backend):
1124-
_backend = choose_backend(backend)
1124+
else:
11251125
if _backend == 'tracemalloc' and has_tracemalloc:
11261126
tracemalloc.start()
1127-
builtins.__dict__['profile'] = profiler
1128-
# shadow the profile decorator defined above
1129-
ns = dict(_CLEAN_GLOBALS, profile=profiler)
11301127
try:
11311128
with open(filename) as f:
11321129
exec(compile(f.read(), filename, 'exec'), ns, ns)
@@ -1135,6 +1132,24 @@ def exec_with_profiler(filename, profiler, backend):
11351132
tracemalloc.stop()
11361133

11371134

1135+
def run_module_with_profiler(module, profiler, backend, passed_args=[]):
1136+
from runpy import run_module
1137+
builtins.__dict__['profile'] = profiler
1138+
ns = dict(_CLEAN_GLOBALS, profile=profiler)
1139+
_backend = choose_backend(backend)
1140+
sys.argv = [module] + passed_args
1141+
if PY2:
1142+
run_module(module, run_name="__main__", init_globals=ns)
1143+
else:
1144+
if _backend == 'tracemalloc' and has_tracemalloc:
1145+
tracemalloc.start()
1146+
try:
1147+
run_module(module, run_name="__main__", init_globals=ns)
1148+
finally:
1149+
if has_tracemalloc and tracemalloc.is_tracing():
1150+
tracemalloc.stop()
1151+
1152+
11381153
class LogFile(object):
11391154
"""File-like object to log text using the `logging` module and the log
11401155
report can be customised."""
@@ -1168,7 +1183,7 @@ def flush(self):
11681183

11691184

11701185
if __name__ == '__main__':
1171-
from argparse import ArgumentParser
1186+
from argparse import ArgumentParser, REMAINDER
11721187

11731188
parser = ArgumentParser(usage=_CMD_USAGE)
11741189
parser.add_argument('--version', action='version', version=__version__)
@@ -1191,18 +1206,28 @@ def flush(self):
11911206
choices=['tracemalloc', 'psutil', 'posix'], default='psutil',
11921207
help='backend using for getting memory info '
11931208
'(one of the {tracemalloc, psutil, posix})')
1194-
parser.add_argument('script', help='script file run on memory_profiler')
1209+
parser.add_argument("program", nargs=REMAINDER,
1210+
help='python script or module followed by command line arguements to run')
11951211
args = parser.parse_args()
11961212

1197-
script_filename = _find_script(args.script)
1213+
if len(args.program) == 0:
1214+
print("A program to run must be provided. Use -h for help")
1215+
sys.exit(1)
1216+
1217+
target = args.program[0]
1218+
script_args = args.program[1:]
11981219
_backend = choose_backend(args.backend)
11991220
if args.timestamp:
12001221
prof = TimeStamper(_backend)
12011222
else:
12021223
prof = LineProfiler(max_mem=args.max_mem, backend=_backend)
12031224

12041225
try:
1205-
exec_with_profiler(script_filename, prof, args.backend)
1226+
if args.program[0].endswith('.py'):
1227+
script_filename = _find_script(args.program[0])
1228+
exec_with_profiler(script_filename, prof, args.backend, script_args)
1229+
else:
1230+
run_module_with_profiler(target, prof, args.backend, script_args)
12061231
finally:
12071232
if args.out_filename is not None:
12081233
out_file = open(args.out_filename, "a")

mprof

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import time
1010
import math
1111

1212
from collections import defaultdict
13-
from argparse import ArgumentParser, ArgumentError
13+
from argparse import ArgumentParser, ArgumentError, REMAINDER, RawTextHelpFormatter
1414

1515
import memory_profiler as mp
1616

@@ -175,7 +175,7 @@ def get_cmd_line(args):
175175

176176
def run_action():
177177
import time, subprocess
178-
parser = ArgumentParser(usage="mprof run [options] program")
178+
parser = ArgumentParser(usage="mprof run [options] program", formatter_class=RawTextHelpFormatter)
179179
parser.add_argument('--version', action='version', version=mp.__version__)
180180
parser.add_argument("--python", dest="python", action="store_true",
181181
help="""Activates extra features when the profiling executable is a Python program (currently: function timestamping.)""")
@@ -186,8 +186,13 @@ def run_action():
186186
parser.add_argument("--include-children", "-C", dest="include_children", action="store_true",
187187
help="""Monitors forked processes as well (sum up all process memory)""")
188188
parser.add_argument("--multiprocess", "-M", dest="multiprocess", action="store_true",
189-
help="""Monitors forked processes creating individual plots for each child""")
190-
parser.add_argument("program", nargs='*')
189+
help="""Monitors forked processes creating individual plots for each child (disables --python features)""")
190+
parser.add_argument("program", nargs=REMAINDER,
191+
help='Option 1: "<EXECUTABLE> <ARG1> <ARG2>..." - profile executable\n'
192+
'Option 2: "<PYTHON_SCRIPT> <ARG1> <ARG2>..." - profile python script\n'
193+
'Option 3: (--python flag present) "<PYTHON_EXECUTABLE> <PYTHON_SCRIPT> <ARG1> <ARG2>..." - profile python script with specified interpreter\n'
194+
'Option 4: (--python flag present) "<PYTHON_MODULE> <ARG1> <ARG2>..." - profile python module\n'
195+
)
191196
args = parser.parse_args()
192197

193198
if len(args.program) == 0:

0 commit comments

Comments
 (0)