mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 59acdba820
			
		
	
	
		59acdba820
		
			
		
	
	
	
	
		
			
			Implement a statistical sampling profiler that can profile external Python processes by PID. Uses the _remote_debugging module and converts the results to pstats-compatible format for analysis. Co-authored-by: Pablo Galindo <pablogsal@gmail.com>
		
			
				
	
	
		
			69 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import io
 | |
| import importlib.machinery
 | |
| import os
 | |
| import sys
 | |
| from optparse import OptionParser
 | |
| 
 | |
| from .profile import runctx
 | |
| 
 | |
| 
 | |
| def main():
 | |
| 
 | |
|     usage = "profile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
 | |
|     parser = OptionParser(usage=usage)
 | |
|     parser.allow_interspersed_args = False
 | |
|     parser.add_option('-o', '--outfile', dest="outfile",
 | |
|         help="Save stats to <outfile>", default=None)
 | |
|     parser.add_option('-m', dest="module", action="store_true",
 | |
|         help="Profile a library module.", default=False)
 | |
|     parser.add_option('-s', '--sort', dest="sort",
 | |
|         help="Sort order when printing to stdout, based on pstats.Stats class",
 | |
|         default=-1)
 | |
| 
 | |
|     if not sys.argv[1:]:
 | |
|         parser.print_usage()
 | |
|         sys.exit(2)
 | |
| 
 | |
|     (options, args) = parser.parse_args()
 | |
|     sys.argv[:] = args
 | |
| 
 | |
|     # The script that we're profiling may chdir, so capture the absolute path
 | |
|     # to the output file at startup.
 | |
|     if options.outfile is not None:
 | |
|         options.outfile = os.path.abspath(options.outfile)
 | |
| 
 | |
|     if len(args) > 0:
 | |
|         if options.module:
 | |
|             import runpy
 | |
|             code = "run_module(modname, run_name='__main__')"
 | |
|             globs = {
 | |
|                 'run_module': runpy.run_module,
 | |
|                 'modname': args[0]
 | |
|             }
 | |
|         else:
 | |
|             progname = args[0]
 | |
|             sys.path.insert(0, os.path.dirname(progname))
 | |
|             with io.open_code(progname) as fp:
 | |
|                 code = compile(fp.read(), progname, 'exec')
 | |
|             spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
 | |
|                                                   origin=progname)
 | |
|             globs = {
 | |
|                 '__spec__': spec,
 | |
|                 '__file__': spec.origin,
 | |
|                 '__name__': spec.name,
 | |
|                 '__package__': None,
 | |
|                 '__cached__': None,
 | |
|             }
 | |
|         try:
 | |
|             runctx(code, globs, None, options.outfile, options.sort)
 | |
|         except BrokenPipeError as exc:
 | |
|             # Prevent "Exception ignored" during interpreter shutdown.
 | |
|             sys.stdout = None
 | |
|             sys.exit(exc.errno)
 | |
|     else:
 | |
|         parser.print_usage()
 | |
|     return parser
 | |
| 
 | |
| # When invoked as main program, invoke the profiler on a script
 | |
| if __name__ == '__main__':
 | |
|     main()
 |