суббота, 13 декабря 2014 г.

python notes

#!/usr/bin/env python

Справочная система

Получить справку по имени (ключевому слову, функции, пакету, ...):
pydoc3 <имя>  
Запустить веб-сервер на свободном порту и открыть заглавную страницу документации в браузере:
pydoc3 -b

*** ipython notebook

ipython - удобная оболочка для работы с интерпретатором. Имеет подсветку синтаксиса, автодополнение и множество других преимуществ перед Python shell. Работа в этой оболочке похожа на работу в математических пакетах (Mathematica, Maxima). [IPython: замена стандартного Python shell]
ipythone notebook - удобная среда для работы с ipython в браузере. Часто используется при научных и инженерных вычислениях, интегрируется с matplotlib, позволяя отображать графики в том же окне, после вызывающего блока. 

комманда запуска: ipython notebook
зайти из браузера на сервер: http://127.0.0.1:8888

включить интеграцию matplotlib:
%matplotlib inline
При необходимости установить размер и разрешение графиков
figure(figsize = (8,4), dpi=300)  # размеры в дюймах
 
# установить размер шрифтов на графиках
matplotlib.rcParams.update({'font.size': 16}) 
В ipython notebook картинка может сжиматься до очень маленького размера, если её фактические размеры слишком велики.

***

Использовать utf-8 символы в скрипте [so]:
# -*- coding: utf-8 -*-  

***

Версия интерпретатора [so]

import sys
>>> sys.version # строка содержащая информацию о версии
>>> sys.version_info # то же самое только в кортеже 
Запустить скрипт в интерактивном режиме
Выполнить скрипт, а после открыть консоль после завершения последней операции. Таким образом, можно пользоваться результатами выполнения скрипта.
python -i script.py

***

Передать код параметром интерпретатора

python -c "print('Hello World')"

Операторы можно разделять точкой с запятой.

Установить зависимости из requirements.txt

pip install -r requirements.txt
***
Установить пакет из скрипта. Скрипт должен быть запущен с правами суперпользователя.

import pip
pip.main(['install', 'python-registry'])  # установка пакета python-registry

Профилирование [wiki]

python -m cProfile -s test <script.py>

Модуль cProfile замеряет время выполнения функций и число вызовов. Данные выводятся в табличном виде.
 14417410 function calls (14416960 primitive calls) in 7.394 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  1000000    3.511    0.000    5.614    0.000 my-script.py:31(my_favorite_foo)

ncalls - число вызовов;
tottome - общее время работы (без учёта вызовов подпрограмм?);
percall - tottome / ncalls;
cumtime - общее время работы;
percall - cumtime / ncalls.

Подробнее: Profiling python with cProfile

vprof - несколько более медленный профилировщик, который однако выдаёт более наглядный результат. Программа создаёт в том числе тепловую карту кода, кодируя цветом время выполнения отдельных фрагментов кода.
После завершения работы python программы будет запущен веб-сервер и показаны разельтаты измерения работы программы. Страница с информацией автоматически откроется в браузере.


Отладка

Встроенный режим отладки есть во многих IDE, включая PyCharm. Однако, можно не прибегая к сторонним средствам воспользоваться встроенным интерактивным консольным отладчиком pdb. Для этого достаточно подключить его как модуль при запуске скрипта:
python3 -m pdb <script>
Программа запустится на выполнение, которое будет приостановлено после первой же инструкции. Список основных команд отладчика можно получить напечатав h. Остальные команды также лаконичны (small cheatsheet):
l - показать окрестности текущей строки
n - step over, next - выполнить следующую строку
s - step into - то же самое, только с входом в функции
c - continue - выполнять до точки останова

b - показать точки останова
b 123 - установить точку останова в строке 123
cl - удалить все точки останова
cl 2 - удалить точку останова с номером 2.



Именованные кортежи (named tuples) [doc]
from collections import namedtuple
Body = namedtuple('Body', 'm v')
b = Body(5, 7)
E = b.m * b.v**2 / 2
E = b[0] * b[1]**2 / 2
m, v = b 

Отдельные поля менять не позволяется, вместо этого можно создать новый кортеж: 
p = Point(x=11, y=22) 
p2 = p._replace(x=33)


***
Инвертировать список [SO]:
>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]
 
 

***

Python String Format Cookbook

Печать списков

Красиво напечатать список состоящий их строк:
print(', '.join(['one', 'two', 'three'])) 
В результате:
one, two, three
Строка для который вызывается метод join является разделитем. После последнего элемента списка разделитель не ставится.
Часто этот способ нужен для того, чтобы отформатировать на печеати числа с плавающей точкой:
lst = [11.334000000000001, 17.058000000000003, 22.782000000000004, 28.506000000000004, 34.230000000000004]
print(', '.join(map(lambda x: "%2.3f"%x, lst)))
Вывод:
11.334, 17.058, 22.782, 28.506, 34.230
Итератор map  применяет к каждому элементу списка lst функцию, что передаётся первым параметром. В примере лямбда-функция в свою чоредь, превращает каждое число из списка lst в строку, которая и передаются уже методу join.

Генераторы списков.

Лаконичный и элегантный способ создать список:
numbers = [1,2,3,4,5]
squares = [number*number for number in numbers] 
Сложить элементы двух списков попарно:
T = [21.036, 31.357, 41.489, 51.442, 61.227]
S = [11.334, 17.058, 22.782, 28.506, 34.230]
ST = [s + t for s, t in zip(S, T)]


*** 
Скрипт запущен под рутом? 
if os.getuid()==0:
    print "user is root" else:  
    print "user is not root"
На счёт переносимости этого кода есть разные мнения, как и на счёт самих способов проверить обладает ли правами суперпользователя скрипт stackoverflow.

***
Проверить синтаксис скрипта без его выполнения [SO]:
python -m py_compile script.py

Параметры скрипта

Получить параметры с которыми скрипт был запущен:
if len(sys.argv):
    param1 = sys.argv[1]


getopt
Скрипт обрабатывает ключи -h, ключи требующие параметра (параметрические) -f и -t (во втором параметре конструктора getopt за этими параметрами следует двоеточие ":"); а также длинные параметрические ключи --file и --text:
import getopt

# объявление и чтение параметров (ключей) скрипта
try:
  opts,args = getopt.getopt(sys.argv[1:],"hf:t:",["file","text"])
except getopt.GetoptError:
  print('invalid params')
 
# обработка ключей opt и их параметров arg
for opt,arg in opts:
  if opt=='-h':
    print(HELP)
  elif opt in ("-f", "--ifile"):
    ifile=arg
    # ...
  elif opt in ("-t", "--text"):
    text=arg
    # ... 

См. также optparse

***

Работа с ini файлами (файлами конфигурации) [SO]
import configparser 
config = configparser.ConfigParser()
config.read('FILE.INI')
print(config['DEFAULT']['path'])  # -> "/path/name/"
config['DEFAULT']['path'] = '/var/shared/'  # update
config['DEFAULT']['default_message'] = 'Hey! help me!!' # create with open('FILE.INI', 'w') as configfile: # save
config.write(configfile)


Регулярные выражения [tutorialspoint]
import re
line = "Ave Satanas!"
reg = re.compile("Ave, [a-zA-Z]*!")
if reg.match(line):
print("match")


Прочитать пароль со стандартного ввода
import getpass
pw = getpass.getpass()

***
Хранить пароли можно в системном хранилище, используя для этого библиотеку keyring:
>>> import keyring  
>>> keyring.set_password("system", "username", "password")  
>>> keyring.get_password("system", "username") 
'password'
 

Вычислить md5 хэш
import hashlib
print(hashlib.md5("whatever your string is".encode('utf-8')).hexdigest())

Процессы и потоки

Из-за использования Global Interpreter Lock в реализации языка CPython потоки фактически вополняются только по одному за раз. Поэтому параллельные вычисления занимают примерно столько же времени сколько и такие же но последовательные.
Выиграть от использование потоком можно только при работе с операциями ввода\вывода, когда можно разделить, например ожидание ввода и одновременное исполнение какого-либо кода [SO].

import threading
from time import clock
from math import sqrt

def foo(x):
    for i in range(50000000): x = sqrt(i)*n
    print("I'm finished: %f"%clock())
    return
t1 = threading.Thread(target= foo, args=(7,))
# запуск кода на выполнение
t1.start()
# ожидание завершения потока
t1.join()



***
Запустить процесс и посмотреть, что из этого получится. Например, попробовать извлечь файлы из запароленого 7z архива:
import subprocess
filename ="qwerty.7z"
password = "qwerty"
s = subprocess.Popen(["7z", "e", "-p"%password, filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
r = s.communicate()[0]

Процессы [doc]

Работа с процессами похожа на работу с потоками:
import multiprocessing
 
def foo(x): 
    print(x) 
 
# создание процесса p = multiprocessing.Process(target = foo, args = (1, )) 
p.start() # запуск 
p.join() # ожидание завершения 
*** Пулы процессов [link]
...
*** Queue and Pipes
...
Параллельное программирование в Python при помощи multiprocessing и shared array

 
***
Запустить приложение, которое продолжит работу после завершения скрипта:
Popen(["application"], stdout=PIPE, stderr=PIPE, close_fds=True)

***
Читать без блокировок вывод (p.stdout.readline()) процесса [stackoverflow].

***
Завершить приложение:
p = Popen(["application"], stdout=PIPE, stderr=PIPE, close_fds=True)
p.kill()
p.wait()

***
Найти процесс по имени среди запущенных в системе:
import psutil
for proc in psutil.process_iter():
if proc.name == "application":
    print("application is running") 

Сеть и Интернет

Загрузить веб страницу
from urllib import request
resp = request.urlopen("http://google.com")
resp.readline()  # содержание страницы


Библиотека для работы с XMPP (jabber) - sleekxmpp

Лёгкий (один файл) веб-фреймворк Bottle,
Легкий python веб-фреймворк: Bottle
Для тестирования можно вместо стороннего сервера использовать сервер встроеный в bottle. Функция run() запускает сервер:
from bottle import route, run 
# функция сработает при запросе страницы hello
@route('/hello') 
def hello():
    return "Hello World!" 
 
run(host='localhost', port=80, debug=True)


По-умолчанию сервер работает на порту 8080. Для пользования 80-го порта могут потребоваться права суперпользователя.

***
Собрать данные с веб-страницы 

Открыть URL в браузре по-умолчанию
import webbrowser
webbrowser.open_new('https://google.com')

Автоматизация браузера

mechanize. тестирование сайтов, заполнение и отправка форм, скачивание файлов и т.п.

selenium


Офис

reportlab
 

Математика в python

***

Pandas

Представляет богатый функционал для обработки данных.
Чтение данных из CSV файла:
pdata = pd.read_csv('file.csv', delimiter=' ')
# Получим привычные списки значений по столбцам
data = pdata.values.transpose()
 
read_csv, в отличаи от аналогичных функции numpy, по-умолчанию способена считывать сложные типы данных, такие как время. Numpy же заменит все не числа так и сохранит: Nan. Однако конвертировать, например время, из строки (как сохранит его после прочтения из csv файла pandas) в специальный формат всё же придётся.
Введение в анализ данных с помощью Pandas
Getting Started with Pandas: Kaggle's Titanic Competition

Геолокация

По публичному IP.
Будем использовать локальную БД (эту):
import GeoIP
gi = GeoIP.open('/usr/share/GeoIP/GeoIPCity.dat', GeoIP.GEOIP_STANDARD)
geo = gi.record_by_addr('8.8.8.8')
Теперь geo содержит словарь:
{'area_code': 650,
 'city': 'Mountain View',
 'country_code': 'US',
 'country_code3': 'USA',
 'country_name': 'United States',
 'dma_code': 807,
 'latitude': 37.384498596191406,
 'longitude': -122.08809661865234,
 'metro_code': 807,
 'postal_code': '94040',
 'region': 'CA',
 'region_name': 'California',
 'time_zone': 'America/Los_Angeles'}

Алсо

LearnPython.org interactive Python tutorial

Ссылки

IPython: замена стандартного Python shell
IPython: Built-in magic commands

Python: советы, уловки, хаки [eng]
Scientific Python Tips and Tricks
Программирование и научные вычисления на языке Python
Параллельное программирование в Python при помощи multiprocessing и shared array
Working with Binary Data in Python, 2015

Книги
  • Лутц М. Изучаем Python, 4-е издание, 2011, 1280 с.; (вышло 5-е издание?). В книге приводится практически полное описание языка, от простого к сложному.
  • Лутц М. Программирование на Python, том I,II, 4-е издание, 2011. Дополнение к предыдущей книге, рассматриваются популярные пакеты, посвящена практике программирования на Python.
  • Gray Hat Python: Python Programming for Hackers and Reverse Engineers; Violent Python - A Cookbook for Hackers, Forensic Analysts, Penetration Testers and Security Engineers; Книга поясвящённая вопросам информационной безопасности, практически полностью состоит из примеров.
---
Подсветка синтаксиса highlight.hohli.com