Архив автора: admin

Руководство по анализу производительности скриптов на Python (Перевод)

Поскольку не каждая программа на Python требует тщательного анализа производительности, отрадно знать, что когда такая необходимость возникает у Вас всё же есть отличные инструменты для этой цели.
Анализ производительности программы состоит в поиске ответа на четыре вопроса:
  1. Как быстро выполняется программа?
  2. Какое место определяет скорость её выполнения?
  3. Как много используется памяти?
  4. Где утечки памяти?
Посмотрим, что же у нас есть для ответа на эти вопросы.

Грубая оценка времени выполнения

Давайте начнём  простого и быстрого способа оценки времени выполнения нашего кода: старой доброй утилиты UNIX time:
$ time python yourprogram.py

real 0m1.028s
user 0m0.001s
sys 0m0.003s

Объяснение этого результата можно найти в этой статье. В кратце:

  • real — время от запуска программы до её завершения
  • user — время процессора, затраченное вне ядра
  • sys — время процессора, затраченное в ядре
Таким образом, сложив user и sys, Вы можете оценить сколько процессорного времени потребовалось вашей программе вне зависимости от загрузки системы.
Если эта сумма сильно больше чем реально затраченное время, тогда можно предположить, что проблемы с производительностью вашей программы связаны с ожиданием ввода / вывода.

Более точная оценка времени с использованием менеджера контекста

Вот маленький модуль, который окажет нам бесценную пользу в измерении времени выполнения:
timer.py
import time

class Timer(object):
def __init__(self, verbose=False):
self.verbose = verbose

def __enter__(self):
self.start = time.time()
return self

def __exit__(self, *args):
self.end = time.time()
self.secs = self.end - self.start
self.msecs = self.secs * 1000 # millisecs
if self.verbose:
print 'elapsed time: %f ms' % self.msecs

Для того, чтобы его использовать, мы должны обернуть тот кусок кода, время выполнения которого Вы хотите замерить в полученный менеджер контекста. Он запускает измерение времени в начале выполнения блока кода и завершает после выполнения. Вот пример использования этого модуля:
from timer import Timer
from redis import Redis
rdb = Redis()

with Timer() as t:
rdb.lpush("foo", "bar")
print "=> elasped lpush: %s s" % t.secs

with Timer as t:
rdb.lpop("foo")
print "=> elasped lpop: %s s" % t.secs
Я обычно сохраняю вывод в файл для того, чтобы отслеживать изменения производительности с ростом программы.

Построчный тайминг и частота выполнения с
помощью profiler

У Robert Kern есть замечательный проект под названием line_profiler, которым я часто пользуюсь для того, чтобы понять, как быстро выполняется каждая строчка моего кода. Чтобы его использовать — Вам надо сперва установить его при помощи pip:
$ pip install line_profiler

После установки можно использовать модуль “line_profiler” или скрипт “kernprof.py”.

Чтобы использовать этот инструмент для начала Вам надо изменить свой код, обернув функцию, производительность которой Вы хотите измерить, в декоратор @profile. Не беспокойтесь, для этого Вам не надо будет ничего импортировать. Скрипт kernprof.py автоматически добавит всё, что нужно в ваш скрипт в процессе выполнения.
primes.py
@profile
def primes(n):
if n==2:
return [2]
elif n<2:
return []
s=range(3,n+1,2)
mroot = n ** 0.5
half=(n+1)/2-1
i=0
m=3
while m <= mroot:
if s[i]:
j=(m*m-3)/2
s[j]=0
while j<half:
s[j]=0
j+=m
i=i+1
m=2*i+3
re turn [2]+[x for x in s if x]
primes(100)
После того, как Вы настроили свой скрипт — используйте usekernprof.py для его запуска.
$ kernprof.py -l -v fib.py
Опция -l указывает kernprof'у добавить декоратор @profile во встроенную область видимости вашего скрипта, а -v указывает kernprof указать информацию о тайминге после выполнения скрипта. Вывод должен выглядеть так:
Wrote profile results to primes.py.lprof
Timer unit: 1e-06 s

File: primes.py
Function: primes at line 2
Total time: 0.00019 s

Line # Hits Time Per Hit % Time Line Contents
==============================================================
2 @profile
3 def primes(n):
4 1 2 2.0 1.1 if n==2:
5 return [2]
6 1 1 1.0 0.5 elif n<2:
7 return []
8 1 4 4.0 2.1 s=range(3,n+1,2)
9 1 10 10.0 5.3 mroot = n ** 0.5
10 1 2 2.0 1.1 half=(n+1)/2-1
11 1 1 1.0 0.5 i=0
12 1 1 1.0 0.5 m=3
13 5 7 1.4 3.7 while m <= mroot:
14 4 4 1.0 2.1 if s[i]:
15 3 4 1.3 2.1 j=(m*m-3)/2
16 3 4 1.3 2.1 s[j]=0
17 31 31 1.0 16.3 while j 18 28 28 1.0 14.7 s[j]=0
19 28 29 1.0 15.3 j+=m
20 4 4 1.0 2.1 i=i+1
21 4 4 1.0 2.1 m=2*i+3
22 50 54 1.1 28.4 return [2]+[x for x in s if x]

Ищите строки с большим значением hits или time. Это те места, где скрипт можно оптимизировать.

Какое количество памяти мы используем?

Теперь, узнав время выполнения нашего кода, давайте посмотрим на объем используемой им памяти. К счастью для нас, Fabian Pedregosa сделал хороший профилировщик памяти.
Для начала установим его при помощи pip:
$ pip install -U memory_profiler
$ pip install psutil
(Установка пакета psutil сильно ускорит работу memory_profiler).
Как и line_profiler, memory_profiler требует декорирования интересующей вас функции при помощи декоратора @profile:
@profile
def primes(n):
...
...
Для того, чтобы посмотреть сколько памяти использует ваша функция запустите скрипт так:
$ python -m memory_profiler primes.py
Вот пример вывода отчёта после завершения работы скрипта:
Filename: primes.py

Line # Mem usage Increment Line Contents
==============================================
2 @profile
3 7.9219 MB 0.0000 MB def primes(n):
4 7.9219 MB 0.0000 MB if n==2:
5 return [2]
6 7.9219 MB 0.0000 MB elif n<2:
7 return []
8 7.9219 MB 0.0000 MB s=range(3,n+1,2)
9 7.9258 MB 0.0039 MB mroot = n ** 0.5
10 7.9258 MB 0.0000 MB half=(n+1)/2-1
11 7.9258 MB 0.0000 MB i=0
12 7.9258 MB 0.0000 MB m=3
13 7.9297 MB 0.0039 MB while m <= mroot:
14 7.9297 MB 0.0000 MB if s[i]:
15 7.9297 MB 0.0000 MB j=(m*m-3)/2
16 7.9258 MB -0.0039 MB s[j]=0
17 7.9297 MB 0.0039 MB while j 18 7.9297 MB 0.0000 MB s[j]=0
19 7.9297 MB 0.0000 MB j+=m
20 7.9297 MB 0.0000 MB i=i+1
21 7.9297 MB 0.0000 MB m=2*i+3
22 7.9297 MB 0.0000 MB return [2]+[x for x in s if x]

Куда утекает память?

Интерпретатор сPython использует счётчик ссылок
для управления памятью. То есть каждый объект содержит счётчик, который увеличивается на 1, когда ссылка на этот объект сохраняется где-то, и уменьшается при удалении этой ссылки. Когда счётчик становится равным нулю интерпретатор cPython знает, что объект больше не используется и можно освободить занимаемую им память.
Утечки памяти могут возникать в вашей программе если где-то сохраняется ссылка на какой-то уже не используемый объект.
Самый быстрый способ поиска таких утечек памяти — использовать восхитительный инструмент objgraph написанный Marius Gedminas. Этот инструмент помогает увидеть количество объектов в памяти и обнаружить разные места в коде, которые содержат ссылки на эти объекты.
Для начала установите objgraph:
pip install objgraph
После этого вставьте в ваш код выражения для вызова отладчика:
import pdb; pdb.set_trace()

Статистика использования объектов

В процессе выполнения Вы можете посмотреть на 20 наиболее используемых объектов в вашей программе:
(pdb) import objgraph
(pdb) objgraph.show_most_common_types()

MyBigFatObject 20000
tuple 16938
function 4310
dict 2790
wrapper_descriptor 1181
builtin_function_or_method 934
weakref 764
list 634
method_descriptor 507
getset_descriptor 451
type 439

Какие объекты были добавлены и удалены?

Для того, чтобы посмотреть, какие объекты были удалены или добавлены между двумя точками сделайте так:
(pdb) import objgraph
(pdb) objgraph.show_growth()
.
.
.
(pdb) objgraph.show_growth() # this only shows objects that has been added or deleted since last show_growth() call

traceback 4 +2
KeyboardInterrupt 1 +1
frame 24 +1
list 667 +1
tuple 16969 +1

Что ссылается на этот «утёкший объект»?

Давайте для примера возьмём простой скрипт:
x = [1]
y = [x, [x], {"a":x}]
import pdb; pdb.set_trace()
Чтобы увидеть, что ссылается на переменную x, вызовите функцию objgraph.show_backref():
(pdb) import objgraph
(pdb) objgraph.show_backref([x], filename="/tmp/backrefs.png")
На выводе Вы получите PNG изображение, сохранённое в/tmp/backrefs.png:
back refrences
Квадрат внизу с красными буквами это и есть интересующий нас объект. Мы можем увидеть, что на него ссылается x один раз и список y три раза. Если x is вызывает утечки памяти, можно воспользоваться этим методом чтобы найти эти забытые ссылки.
Ещё раз: objgraph позволяет нам:
  • посмотреть N популярных объектов в памяти вашей программы
  • посмотреть какие объекты были удалены и добавлены за какой-то период времени
  • посмотреть все ссылки на заданный объект в нашем скрипте

Эффективность против точности

В этом посте я показал несколько инструментов анализа производительности программ на Python. Вооружённые этими инструментами Вы можете получить всю нужную информацию для поиска утечек памяти и бутылочных горлышек в вашем скрипте.
Как и во многих других случаях, точность анализа и скорость его выполнения зависят одно от другого. Так что если Вы сомневаетесь — используйте минимальное решение, удовлетворяющее ваши нужды.
Ссылки

Источник

Автор: Ishayahu Lastov

Релиз CFFI 0.2

Вышел релиз CFFI 0.2 (а вскоре ожидается и 1.0). CFFI это способ вызова C из Python. Этот релиз касается только CPython 2.6 или 2.7. Поддержка PyPy будет в ветке ffi-backend, но она ещё не реализована.Поддержку CPython 3.x сделать легко, но нужна для этого помощь.
Пакет доступен на bitbucket и хорошо документирован. Кроме того Вы можете просто установить его из python package index: pip install cffi
В этом релизе:
  • Многочисленные небольшие изменения и поддержка большего количества Си-измов
  • Большая новость: поддержка installing packages которые используют ffi.verify() на машина без компилятора C. Возможно это снимает последнее ограничение, которое удерживало людей от использования CFFI.
  • Некоторые небольшие изменения:
    • отображение между 'wchar_t' и Python юникодом
    • введение ffi.NULL
    • возможно более ясное API для ffi.new(): т.е. для того, чтобы выделить единичный int и получить указатель на него, используйте ffi.new(«int *») вместо старого ffi.new(«int»)
    • и, конечно, множество маленьких исправлений
  • CFFI использует pkg-config при наличии для собственной установки. Это помогает определить место libffi на современных Linux. Поддержка Mac OS/X тоже доступна (смотрите детальные инструкции по установке). Win32 должен работать из коробки. Win64 реально ещё не тестирован.

    Автор: Ishayahu Lastov

    Мои бывшие мужчины ))))

    МОИ БЫВШИЕ))))))))

    Роберто… Моя первая любовь… Женился сволочь…

    moibivshie 13

    *********************************************************************

    Это Юра. С ним мне приходилось делить ещё и свою дамскую комнату…

    moibivshie 21

    *********************************************************************

    Даня  своей дерзостью мог любого заткнуть… спрятавшись за моей спиной

    moibivshie 39

    ****************************************************

    Ренат… выпылесосил все мои сбережения

    moibivshie 40

    ***************************************************

    Это Сережа… Он умел делать сюрпризы

    moibivshie 1

    **************************************** Читать →

    Сериал "Python PDF" – Обзор metaPDF (Перевод)

    Исследуя библиотеки для работы с PDF на Python, я наткнулся на ещё один маленький проект с названием metaPDF. Судя по указанному на сайте этого проекта, metaPDF это лёгкая библиотека для Python, оптимизированная для получения и вставки метаданных, по сути это легковесная обёртка вокруг замечательной библиотеки pyPdf. Я не уверен в том, что эта библиотека будет полена с учётом возможности работы с самой библиотекой pyPdf, так что давайте посмотрим на неё в деле.

    Получение и использование metaPDF

    Процесс установки metaPDF достаточно прост, особенно если использовать easy_install или pip. После этого давайте запустим маленький скрипт для того, чтобы посмотреть, как он работает. Вот пример, основанный на информации с github:
    from metapdf import MetaPdfReader
     
    pdfOne = r'C:UsersmdriscollDocumentsreportlab-userguide.pdf'
    x = MetaPdfReader()
    metadata = x.read_metadata(open(pdfOne, 'rb'))
    print metadata
    Я запускаю скрипт к руководству по Reportlab. Обратите внимание, что в оригинале есть опечатка — там используется “read” для открытия файла. Я полагаю, что он не будет работать, пока Вы сам не откроете файл. В любом случае, вот результат работы этого скрипта:
    {'/ModDate': u'D:20120629155504', '/CreationDate': u'D:20120629155504', '/Producer': u'GPL Ghostscript 8.15', '/Title': u'reportlab-userguide.pdf', '/Creator': u'Adobe Acrobat 10.1.3', '/Author': u'mdriscoll'}
    Я правда не знаю, каким образом изменилось поле «автор» в документе, но я определённо им не являюсь. Так же я не понимаю, откуда в названии ключей берутся прямые слешы. Судя по исходникам, это всё, что может делать эта библиотека. Разочарованы?  Может быть, если мы проявим внимание к этой библиотеке, автор добавит ей функциональности…

    Автор: Ishayahu Lastov

    Позитивчик)))

    1. Самое тяжелое в жизни — это синий кит, все остальное пустяки!

    ************************

    2. «Доброе утро» — это когда на часах 11:00, на календаре суббота, а за окном атлантический океан.

    ************************

    3. Когда ваши дела идут плохо – не ходите с ними.

    ************************

    4. Время, потерянное с удовольствием, не считается потерянным.

    ************************

    5. Если кто-то на вас ругается, злится или обижается — задавите его своим позитивом.

    ************************

    6. Деньги – зло. Придешь в магазин, прямо зла не хватает.

    ************************

    7. Когда мне было 5 лет, мама всегда твердила мне, что самое важное в жизни — быть счастливым. Когда я пошел в школу, меня спросили, кем я хочу стать, когда вырасту. Я написал «счастливым». Мне сказали » «ты не понял задание», я им сказал — «вы не поняли жизнь».

    ************************

    8. Я знаю, что счастье не купишь. Но можно купить яхту и попробовать подплыть к нему поближе.

    ************************

    9. Спасибо тем людям, которые вошли в мою жизнь и сделали её прекрасной. И ещё, спасибо тем людям, которые вышли из неё, и сделали её ещё лучше.

    ************************

    10. Всегда найдется кто-то, кому не нравится то, что ты делаешь. Это нормально. Всем подряд нравятся только котята.

    ************************

    11. Выйти замуж после двух дней знакомства – просто верх легкомыслия. Надо все хорошенько обдумать. Дней пять!

    ************************

    12. Самый хороший учитель в жизни – опыт. Берет, правда, дорого, но объясняет доходчиво.

    ************************

    13. Есть 3 вещи, которые человек не сможет сделать никогда в своей жизни: посчитать волосы на голове, помыть глаза с мылом, дышать с высунутым языком.

    Ну все все, можешь, засовывай язык назад, молодец. :-)

    RealTraf VK-Message до 35$ за 1000 кликов


    RealTraf. Первое, на что нужно обратить ваше внимание, – это ценовые категории. Если вы хотите зарабатывать на сайте нормально, то ставки необходимо выбрать по максимуму. Именно такие ставки предлагает партнерка Realtraf

    Высокие цены среди аналогичных проектов на покупку трафика
    Минимум к выплате 1 доллар
    Выплаты ежедневные (можно настроить ежедневный автоматический вывод в 00:00)
    Партнерская программа 7%
    Отзывчивая техническая поддержка (на вопросы отвечает быстро и вежливо)

    Возможности заработка для вебмастера:

    — попандер PopUnder/ClickUnder  или PopUp Banner

    — всплывающее сообщение VK-Message

    — всплывающий баннер PeelDown

    — уже который месяц обещают добавить тизерную рекламу, пока ждем…

    Требования для добавления площадки хорошие: ежедневная посещаемость от 250 человек, трафик с поисковых систем от 30%, доступ к статистике LiveInternet. Если у Вас площадка качественная, то ее без проблем примут в ПП RealTraf.

    MessageBox (VK-message)

    Если вы достаточно внимательны, то, наверное, уже заметили на многих больших развлекательных порталах чрезвычайно выгодный на сегодняшний день формат MessageBox (VK-message). Он абсолютно идентичен сообщению, показывающемуся пользователям соцсети Вконтакте.

    Видите, насколько внешнее сходство поразительно, – это в несколько раз повысит вероятность перехода. Значит, обеспечит и повышенную вероятность конвертации трафика. Самый конвертабельный трафик, если говорить о заработке в интернете, – это сайты кино, развлекательные порталы, сайты, посвященные соцсетям, варезники.

    Ставка выкупа по формату MessageBox (VK-message) у веб-мастеров составляет до 70 вмз долларов за 1000 кликов.

    Таргетинг происходит по времени показа. Можно выставить свою цену, ведь MessageBox (VK-message) выкупается на основе аукциона. Существуют и ограничения на показ рекламы на adult-сайтах.

    Данный формат наиболее выгоден, а потому он в момент разбирается рекламодателями, это уже само по себе — хороший индикатор.

    Слайдер

    Дальше формат — слайдер, он очень хорошо успел себя зарекомендовать ранее. Очень неплохой способ заработка на сайте. Тематическое направление сайтов — то же самое, от своих главных конкурентов слайдер отличается обновленными рекламными кампаниями, незнакомыми посетителям. Как итог — увеличение вероятного конверта.

    По формату Slider, ставка выкупа у веб-мастеров составляет до 15 долларов за 1000 кликов.

    Таргетинг работает по времени показа.

    Кликандер

    Выгоднейший формат, а также неплохие ставки для рекламодателей – это кликандер. Он обеспечивает устойчивую стабильность профита и позволяет выгодно проводить конвертацию трафика и зарабатывать на развлекательных порталах. В плюсах — быстрая модерация, несмотря на большой спрос у реклов.

    RealTraf.



    Источник: trafficvip