Время, затраченное на импорт в Python - PullRequest
11 голосов
/ 20 апреля 2009

Я хочу знать, сколько времени занимает импорт как для встроенных, так и для пользовательских модулей.

Ответы [ 7 ]

6 голосов
/ 30 апреля 2012

Один из способов импорта профилей - использовать модуль profile_imports, используемый в bzr исходный код :

# put those two lines at the top of your script
import profile_imports
profile_imports.install()

# display the results
profile_imports.log_stack_info(sys.stderr)

Помимо предоставления времени для импорта, он также оценивает время для составления регулярных выражений, что часто является существенной причиной замедления импорта.

5 голосов
/ 20 апреля 2009

Вы можете проверить это выполнение

$ time python -c "import math"

Однако, что бы это вам помогло? Импорт происходит только один раз и почти никогда не будет бутылочным горлышком. Импорт одного и того же модуля снова и снова не будет выполняться значительно медленнее, чем импорт одного раза, поскольку Python отслеживает, какие модули уже были импортированы.

Чего вы на самом деле пытаетесь достичь?

3 голосов
/ 30 августа 2018

Начиная с версии Python3.7, доступна новая опция -X importtime. Чтобы измерить время импорта, просто запустите ваш скрипт с этой опцией, например, python -X importtime my_script.py.

Для справки:

3 голосов
/ 20 апреля 2009

Чтобы узнать, сколько времени занимает импорт, возможно, самый простой способ - использовать модуль timeit ..

>>> import timeit
>>> t = timeit.Timer('import urllib')
>>> t.timeit(number = 1000000)
0.98621106147766113

То есть, чтобы импортировать urllib 1 миллион раз, это заняло чуть меньше секунды (на Macbook Pro) ..

У меня есть мастер-скрипт, который импортирует другие модули. Мне нужно рассчитать, сколько времени это займет

Если вы имеете в виду общее время выполнения сценария, в Linux / OS X / Cygwin вы можете запустить сценарий с помощью команды time, например:

$ time python myscript.py 

real    0m0.046s
user    0m0.024s
sys     0m0.020s

(помните, что включает в себя все время запуска интерпретатора Python, а также фактическое время выполнения кода, хотя это довольно тривиальная сумма)

Другой, возможно, более полезный способ - профилировать скрипт:

Вместо запуска кода с

$ python myscript.py 

.. вы используете ..

$ python -m cProfile myscript.py
         1059 function calls in 0.015 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.002    0.002    0.015    0.015 myscript.py:1(<module>)
   [...]

Я не нахожу вывод командной строки очень простым для чтения, поэтому я почти всегда использую gprof2dot , который превращает информацию о профилировании в симпатичный граф графика:

$ python -m cProfile -o myscript.prof myscript.py
$ python gprof2dot.py -o myscript.dot -f pstats myscript.prof
$ dot -Tpng -o profile.png prof_runtest.dot -Gbgcolor=black

Пример вывода (1429x1896px PNG)

1 голос
/ 20 апреля 2009

Использовать cProfile:

python -m cProfile yourscript.py
0 голосов
/ 16 июля 2016

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

import os
import sys
import time


class ImportEventNode(object):
    def __init__(self, name, start_time, children=None, end_time=None):
        self.name = name
        self.start_time = start_time
        self.children = [] if children is None else children
        self.end_time = end_time

    def __repr__(self):
        return 'ImportEventNode({self.name}, {self.start_time}, children={self.children}, end_time={self.end_time})'.format(self=self)

    @property
    def total_time(self):
        return self.end_time - self.start_time

    @property
    def net_time(self):
        return self.total_time - sum(child.total_time for child in self.children)


root_node = cur_node = None

all_nodes = []
old_import = __import__
def __import__(*args, **kwargs):
    global root_node, cur_node
    name = args[0]
    if name not in sys.modules:
        t0 = time.time()
        if root_node is None:
            root_node = prev_node = cur_node = lcur_node = ImportEventNode(args[0], t0)
        else:
            prev_node = cur_node
            cur_node = lcur_node = ImportEventNode(name, t0)
            prev_node.children.append(cur_node)
        try:
            ret = old_import(*args, **kwargs)
        finally:
            lcur_node.end_time = time.time()
        all_nodes.append(lcur_node)
        cur_node = prev_node
        return ret
    else:
        return old_import(*args, **kwargs)


__builtins__.__import__ = __import__

Работая на простом примере, вот как это выглядит при импорте scipy.stats:

:import scipy.stats
:
:nodes = sorted(all_nodes, key=(lambda x: x.net_time), reverse=True)
:for node in nodes[:10]:
:    print(node.name, node.net_time)
:
:<EOF>
('pkg_resources', 0.08431100845336914)
('', 0.05861020088195801)
('decomp_schur', 0.016885995864868164)
('PIL', 0.0143890380859375)
('scipy.stats', 0.010602712631225586)
('pkg_resources._vendor.packaging.specifiers', 0.007072925567626953)
('add_newdocs', 0.00637507438659668)
('mtrand', 0.005497932434082031)
('scipy.sparse.linalg', 0.005171060562133789)
('scipy.linalg', 0.004471778869628906)
0 голосов
/ 20 апреля 2009

Проверено на Windows в Python 2.4 - вы можете попробовать сами.

>>> import time

>>> ## Built-in module
>>> def testTime():
        now = time.clock() # use time.time() on unix-based systems
        import math
        print time.clock() - now

>>> testTime()
7.54285810167e-006



>>> ## My own module
>>> def testTime():
        now = time.clock()
        import myBuiltInModule # Not its actual name ;-)
        print time.clock() - now

>>> testTime()
0.00253174635324
>>> testTime()
3.70158777141e-006

Таким образом, существует большая разница между кэшированными модулями и теми, которые вводятся с нуля. Чтобы проиллюстрировать это, мы можем перезагрузить модуль:

>>> def testTime():
        now = time.clock()
        reload(myBuiltInModule )
        print time.clock() - now


>>> testTime()
0.00250017809526
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...