Профилирование Python - PullRequest
       10

Профилирование Python

4 голосов
/ 03 октября 2011

Я написал пару модулей на Python для генерации факториалов, и я хочу проверить время выполнения. Я нашел пример профилирования здесь и использовал этот шаблон для профилирования своих модулей:

import profile #fact

def main():
    x = raw_input("Enter number: ")
    profile.run('fact(int(x)); print')
    profile.run('factMemoized(int(x)); print')

def fact(x):
    if x == 0: return 1
    elif x < 2: return x
    else:
        return x * fact(x-1)

def factMemoized(x):
    if x == 0: return 1
    elif x < 2: return x
    dict1 = dict()
    dict1[0] = 1
    dict1[1] = 1
    for i in range (0, x+1):
        if dict1.has_key(i): pass
        else: dict1[i] = i * dict1[i-1]
    return dict1[x]

if __name__ == "__main__":
    main()

Однако я получаю следующую ошибку:

Enter number: 10
Traceback (most recent call last):
  File "fact.py", line 32, in <module>
    main()
  File "fact.py", line 7, in main
    profile.run('fact(int(x)); x')
  File "C:\Python27\lib\profile.py", line 70, in run
    prof = prof.run(statement)
  File "C:\Python27\lib\profile.py", line 447, in run
    return self.runctx(cmd, dict, dict)
  File "C:\Python27\lib\profile.py", line 453, in runctx
    exec cmd in globals, locals
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined

Есть идеи, что я здесь делаю не так? ТИА! ~ Craig

Ответы [ 4 ]

7 голосов
/ 03 октября 2011

Как сказал Джон Гейнс-младший, profile.run() имеет некоторые проблемы с областью видимости. Однако вы можете просто использовать runctx с globals () и locals () и явно указать контекст:

profile.runctx('fact(int(x)); print', globals(), locals())

Явное лучше, чем неявное:)

6 голосов
/ 03 октября 2011

Профилировщик получает строку, которую он пытается интерпретировать.Ваша строка - profile.run('fact(int(x)); print'), а переменная x внутри является лишь частью строки и не может быть преобразована в переменную.Вы должны скопировать его значение в строку, чтобы сделать эту работу.Попробуйте это:

profile.run('fact(int(%s)); print' % x)
profile.run('factMemoized(int(%s)); print' % x)
3 голосов
/ 03 октября 2011

Правка (убрал мой «ответ», так как у Петра Викторина есть гораздо лучший смысл). Но оставим объяснение, почему он не сработал так, как ожидал OP.

Глядя на код в profile.py (Python 2.7.2), я вижу следующее для методов класса Profile:

def run(self, cmd):
    import __main__
    dict = __main__.__dict__
    return self.runctx(cmd, dict, dict)

def runctx(self, cmd, globals, locals):
    self.set_cmd(cmd)
    sys.setprofile(self.dispatcher)
    try:
        exec cmd in globals, locals
    finally:
        sys.setprofile(None)
    return self

Оператор exec в runctx () подается __main__.__dict__ как для глобальных, так и для локальных словарей, поэтому profile.run () сможет разрешать только те переменные, которые определены в словаре верхнего уровня работающего приложения.

0 голосов
/ 10 февраля 2019

Вы можете напрямую профилировать свой код с помощью Region Profiler . Ваш фрагмент кода будет выглядеть так:

import region_profiler as rp  # pip install region-profiler

rp.install()

def main():
    x = raw_input("Enter number: ")
    fact(int(x))  # note: direct call
    factMemoized(int(x))

@rp.func(asglobal=True)
def fact(x):
    if x == 0: return 1
    elif x < 2: return x
    else:
        return x * fact(x-1)

@rp.func(asglobal=True)
def factMemoized(x):
    if x == 0: return 1
    elif x < 2: return x
    dict1 = dict()
    dict1[0] = 1
    dict1[1] = 1
    for i in range (0, x+1):
        if dict1.has_key(i): pass
        else: dict1[i] = i * dict1[i-1]
    return dict1[x]

if __name__ == "__main__":
    main()

Пример вывода:

name                 total  % of total  count       min   average       max
----------------  --------  ----------  -----  --------  --------  --------
<main>             3.601 s     100.00%      1   3.601 s   3.601 s   3.601 s
. fact()            863 us       0.02%      1    863 us    863 us    863 us
. factMemoized()  73.12 us       0.00%      1  73.12 us  73.12 us  73.12 us
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...