包装 Python cProfile runctx API 以参数化任何地方运行

Wrapping Python cProfile runctx API to parameterize runs with anything anywhere

使用 Python 3.7.2,

我正在尝试将 cProfile.runctx() 包装到一个单独的模块中,例如来自我的主模块 mymain.pyutil.profile_runs() 以分析主模块中的函数。这需要在 util.profile_runs().

中导入 mymain.py

但是,我无法 importlib 使用 util.py 中的以下代码:

import cProfile as profile
import importlib.util
from os.path import basename, splitext
from pprint import pprint
import pstats
import sys

def profile_runs(funcname, modulefile, nruns=5):
    importlib.machinery.SOURCE_SUFFIXES.append('')
    module_name = splitext(basename(modulefile))[0]
    spec = importlib.util.spec_from_file_location(module_name, modulefile)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    # if desired: importlib.machinery.SOURCE_SUFFIXES.pop()

    pprint(dir(module))

    for i in range(nruns):
        filename = 'profile_{}_{}.stats'.format(funcname, i)
        profile.runctx('print({}, {}.{}())'.format(i, module_name, funcname), globals(), locals(), filename)

    # Read all 5 stats files into a single object
    stats = pstats.Stats('profile_stats_0.stats')

    for i in range(1, nruns):
        stats.add('profile_{}_{}.stats'.format(funcname, i))

    # Clean up filenames for the report
    stats.strip_dirs()

    # Sort the statistics by the cumulative time spent
    # in the function
    stats.sort_stats('cumulative')
    stats.print_stats()

mymain.py:

import util

def func_to_profile()
    print('running func_to_profile')

if __name__ == '__main__':
    util.profile_runs('funct_to_profile')

pprint(dir(module)) 行输出模块的正确信息,但 .runctx 调用一直说:

NameError: name 'mymain' is not defined

如果我在 util.profile_runs() 代码中显式 import mymain,它就会工作。 以这种方式描述是不是一个坏主意?

我找到了一个解决方法:只需在 运行 字符串中插入 import module_name;,如下所示:

profile.runctx('import {};print({}, {}.{}())'.format(module_name, i, module_name, funcname), globals(), locals(), filename)

并摆脱整个 importlib 舞蹈。