Skip to content

Commit da8c556

Browse files
Added importer support to profiling
1 parent b4197da commit da8c556

2 files changed

Lines changed: 52 additions & 33 deletions

File tree

‎Lib/profile.py‎

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
# governing permissions and limitations under the License.
2424

2525

26-
import importlib.machinery
27-
import io
2826
import sys
2927
import time
3028
import marshal
@@ -562,7 +560,9 @@ def f(m, f1=f1):
562560

563561
def main():
564562
import os
563+
import runpy
565564
from optparse import OptionParser
565+
from pkgutil import get_importer
566566

567567
usage = "profile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
568568
parser = OptionParser(usage=usage)
@@ -589,25 +589,35 @@ def main():
589589

590590
if len(args) > 0:
591591
if options.module:
592-
import runpy
593592
code = "run_module(modname, run_name='__main__')"
594593
globs = {
595594
'run_module': runpy.run_module,
596595
'modname': args[0]
597596
}
598597
else:
599598
progname = args[0]
599+
importer = get_importer(progname)
600600
sys.path.insert(0, os.path.dirname(progname))
601-
with io.open_code(progname) as fp:
602-
code = compile(fp.read(), progname, 'exec')
603-
spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
604-
origin=progname)
605-
globs = {
606-
'__spec__': spec,
607-
'__file__': spec.origin,
608-
'__name__': spec.name,
609-
'__package__': None,
610-
}
601+
602+
if importer is not None:
603+
code = "run_module_as_main('__main__', alter_argv=False)"
604+
globs = {
605+
"run_module_as_main": runpy._run_module_as_main,
606+
}
607+
else:
608+
import io
609+
import importlib.machinery
610+
611+
with io.open_code(progname) as fp:
612+
code = compile(fp.read(), progname, 'exec')
613+
spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
614+
origin=progname)
615+
globs = {
616+
'__spec__': spec,
617+
'__file__': spec.origin,
618+
'__name__': spec.name,
619+
'__package__': None,
620+
}
611621
try:
612622
runctx(code, globs, None, options.outfile, options.sort)
613623
except BrokenPipeError as exc:

‎Lib/profiling/tracing/__init__.py‎

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ def main():
150150
import runpy
151151
import pstats
152152
from optparse import OptionParser
153+
from pkgutil import get_importer
153154
usage = "cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
154155
parser = OptionParser(usage=usage)
155156
parser.allow_interspersed_args = False
@@ -183,27 +184,35 @@ def main():
183184
}
184185
else:
185186
progname = args[0]
187+
importer = get_importer(progname)
186188
sys.path.insert(0, os.path.dirname(progname))
187-
with io.open_code(progname) as fp:
188-
code = compile(fp.read(), progname, 'exec', module='__main__')
189-
spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
190-
origin=progname)
191-
module = importlib.util.module_from_spec(spec)
192-
# Set __main__ so that importing __main__ in the profiled code will
193-
# return the same namespace that the code is executing under.
194-
sys.modules['__main__'] = module
195-
# Ensure that we're using the same __dict__ instance as the module
196-
# for the global variables so that updates to globals are reflected
197-
# in the module's namespace.
198-
globs = module.__dict__
199-
globs.update({
200-
# Set __spec__ to None so the profiled program behaves like a
201-
# script run directly (gh-140729).
202-
'__spec__': None,
203-
'__file__': spec.origin,
204-
'__name__': spec.name,
205-
'__package__': None,
206-
})
189+
190+
if importer is not None:
191+
code = "run_module_as_main('__main__', alter_argv=False)"
192+
globs = {
193+
"run_module_as_main": runpy._run_module_as_main,
194+
}
195+
else:
196+
with io.open_code(progname) as fp:
197+
code = compile(fp.read(), progname, 'exec', module='__main__')
198+
spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
199+
origin=progname)
200+
module = importlib.util.module_from_spec(spec)
201+
# Set __main__ so that importing __main__ in the profiled code will
202+
# return the same namespace that the code is executing under.
203+
sys.modules['__main__'] = module
204+
# Ensure that we're using the same __dict__ instance as the module
205+
# for the global variables so that updates to globals are reflected
206+
# in the module's namespace.
207+
globs = module.__dict__
208+
globs.update({
209+
# Set __spec__ to None so the profiled program behaves like a
210+
# script run directly (gh-140729).
211+
'__spec__': None,
212+
'__file__': spec.origin,
213+
'__name__': spec.name,
214+
'__package__': None,
215+
})
207216

208217
try:
209218
runctx(code, globs, None, options.outfile, options.sort)

0 commit comments

Comments
 (0)