Обертывание Python cProfile runctx API для параметризации работает с чем угодно и где угодно - PullRequest
0 голосов
/ 30 мая 2019

Использование Python 3.7.2,

Я пытаюсь обернуть cProfile.runctx() в отдельный модуль, такой как util.profile_runs() из моего основного модуля mymain.py, для профилирования функций в основном модуле.Это требует импорта mymain.py в util.profile_runs().

Однако я не смог заставить 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

Это работает, если я явно import mymain вutil.profile_runs() код.Это плохая идея для профилирования таким образом?

1 Ответ

0 голосов
/ 30 мая 2019

Я нашел обходной путь: просто вставьте import module_name; в строку выполнения, например:

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

и избавьтесь от всего importlib танца.

...