2017/06/23

Przykładowa praca zaliczeniowa

W 2012 roku, prowadząc zajęcia na WSB zamieściłem na swojej stronie przykładową pracę zaliczeniową. Strona ją zawierająca była od tamtego czasu najczęściej odwiedzaną podstroną. W związku z tym zamieszczam ją i tutaj - by było ją łatwiej odnaleźć. Tak jak i na tamtej stronie zwracam uwagę:
,,Bez konsultacji z prowadzącym nie zawsze będą Państwo wiedzieć, który styl jest ,,lepszy'', a który ,,gorszy''. Praca którą udostępniam została już ,,zaliczona'', można więc przypuszczać, że jest pracą przynajmniej akceptowalną.''
Podkreślam - ta praca została już ,,zaliczona'', nie można jej więc oddawać jako własnej. Jest ona moją własnością, proszę więc jej nie redystrybuować inaczej, niż z linkiem do wrobelmaciek.info lub wrobelmaciek.blogspot.com.

Tutaj link do pracy udostępnionej przez google drive: https://drive.google.com/file/d/0B91KeMYac8JcZHhHMVNXVGVsREE/preview


openssl - Jak wygenerować samopodpisany certyfikat jednolinijkowcem (oneliner self-signed certificate)

Potrzebujesz samopodpisany certyfikat (self-signed certificate)? Możesz wygenerować go korzystając z openssl-a, dostępnego na praktycznie każdym systemie* poniższym jednolinijkowcem:
openssl req -subj '/CN=twojadomena/O=nazwa twojej firmy/C=PL'  -new -newkey rsa:2048 -days 365 -nodes -x509 -sha256 -keyout server.key -out server.crt
W plikach server.key i server.crt znajdzie się klucz prywatny podpisujący certyfikat i sam certyfikat, odpowiednio.


* na większości linuxów openssl jest zainstalowany domyślnie. Na Windowsie można z niego korzystać przy pomocy Cygwina, lub też zainstalować samodzielne binaria - zob. na stronce projektu.

2017/02/13

Przeszukiwanie dokumentów XML przy pomocy XPath

Przeszukiwanie dokumentów XML przy pomocy XPath

Dokumenty XML są standardem przechowywania i przekazywania danych. Xpath natomiast jest jedną z podstawowych metod przeszukiwania XMLi. Jak więc w Pythonie przeszukiwać xmle?
Python posiada w bibliotece standardowej parser XML - moduł xml. Jednak moduł ten ma ograniczone wsparcie dla XPath (zobacz xpath support na docs.python.org). Bogatsze wsparcie dla XPath zapewnia biblioteka lxml, oparta na libxml2 i libxslt - dobrze rozwiniętych i dostępnych na wiele platform bibliotek. lxml można łatwo zainstalować przy pomocy pip-a, jest wśród standardowych pakietów anacondy, a ze względu na zależności często jest zainstalowany także na linuxowych systemach (zależy od niego np. Inkscape i Cinnamon).
Poniższy program, kompatybilny z Python 3, przedstawia przykłady użycia lxml do parsowania XML z wykorzystaniem XPath.

'''przykladowy program parsujacy XMLe'''
from lxml import etree

# przykladowy xml wczytany bezposrednio z lancucha bajtow.
xml = etree.fromstring(b'''<?xml version="1.0" encoding="UTF-8"?>
<ksiazki>
  <ksiazka>
    <tytul lang="pl">Pan Tadeusz</tytul>
    <autor>A. Mickiewicz</autor>
    <rok>2012</rok>
    <cena>31.99</cena>
  </ksiazka>
  <ksiazka>
    <tytul lang="pl">Antygona</tytul>
    <autor>Sofokles</autor>
    <rok>2006</rok>
    <cena>5.99</cena>
  </ksiazka>
  <f:ksiazka xmlns:f="https://wrobelmaciek.blogspot.com/ksiazki">
    <f:tytul lang="pl">Emocjonalne wampiry w pracy</f:tytul>
    <f:autor>A. B. Bernstein</f:autor>
    <f:rok>2014</f:rok>
    <f:cena>37.90</f:cena>
  </f:ksiazka>
</ksiazki>
''')

#metoda xpath zwraca liste elementow spelniajacych kryteria
#elementy sa objektami, mozna odczytac ich tekst, wziac przodka, 
#atrybuty itd.
print('autorzy ksiazek i jezyk tytulu')
for el in xml.xpath('.//autor'):
    print('{0}:{1}'.format(el.text,
                           el.getparent().find('tytul').get('lang'), ))


#lxml obsluguje tez bardziej zlozone zapytania
print('tytuly ksiazek zaczynajace sie na A:')
print('\n'.join([x.text for x in  
    xml.xpath('.//*[name()="tytul" and starts-with(text(),"A")]')]))

#lxml obsluguje tez przestrzenie nazw (namespaces)
print('''autorzy o nazwiskach zaczynajacych sie na A, 
niezależnie od przestrzeni nazw:''')
print('\n'.join(['%s %s'%(x.tag,x.text,) for x in  
    xml.xpath('.//*[local-name()="autor" and starts-with(text(),"A")]')]))

print('''ksiazki o autorach zaczynajacych sie na A, 
z przestrzeni nazw {https://wrobelmaciek.blogspot.com/ksiazki}:''')
print('\n'.join(['%s %s'%(x.tag,x.text,) for x in
    xml.xpath('.//g:autor[starts-with(text(),"A")]',
    namespaces={'g':'https://wrobelmaciek.blogspot.com/ksiazki'})]))


#jesli nie potrzebujemy zlozonych zapytan, mozemy uzyc tez findall
#kompatybilnego z xml.ElementTree z biblioteki standardowej pythona
print('autorzy ksiazek i jezyk tytulu - findall')
for el in xml.findall('.//autor'):
    print('{0}:{1}'.format(el.text,
                           el.getparent().find('tytul').get('lang'), ))


#findall obsluguje tylko najprostsze zapytania XPath
try:
    print('to nie zadziala')
    for el in xml.findall('.//*[name()="autor"]'):
        print('{0}:{1}'.format(el.text,
                               el.getparent().find('tytul').get('lang'),
        ))
except SyntaxError:
    print('zbyt skomplikowany predykat')

2017/01/23

Jak działa algorytm map-reduce?

Map, Reduce i wielowątkowość w Pythonie

MapReduce jest własnościową platformą Google do przetwarzania równoległego. Nazwa sugeruje związek z operacjami map i reduce, jednak przeglądając przykłady, spotkałem się od razu z pojęciami mapperów, reduktorów, partycjonerów itd, bezpośrednio powiązanych z implementacjami realizującymi algorytm (jak np. hadoopowy mapreduce).
Poniższy przykład ilustruje podstawy algorytmu przy pomocy elementarnych elementów biblioteki standardowej Pythona - metody map z multiprocessing.pool i reduce z functools (w Pythonie 2 będącej funkcją podstawową).
Program wieloprocesowo zlicza wystąpienia poszczególnych znaków w zadanym ciągu liter.
'''prosty wielowatkowy program
ilustrujacy idee algorytmu map-reduce'''

import multiprocessing
from functools import reduce

def policz_litery(lancuch):
    '''funkcja map'''
    unikalne_znaki = set(lancuch)
    wystapienia = { k:0 for k in unikalne_znaki }
    for litera in lancuch:
        wystapienia[litera] += 1
    return wystapienia

def polacz_slowniki(slownik1, slownik2):
    '''funkcja redukuje dwa slowniki z licznikami liter do jednego slownika'''
    wynik = slownik1
    for litera in slownik2.keys():
        if litera in wynik:
            wynik[litera] += slownik2[litera]
        else:
            wynik[litera] = slownik2[litera]
    return wynik

#tekst w ktorym policzymy wystapienia liter
lorem_ipsum = '''Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, sed do eiusmod 
tempor incididunt ut labore et dolore magna aliqua. 
Ut enim ad minim veniam, quis nostrud exercitation 
ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in 
voluptate velit esse cillum dolore eu 
fugiat nulla pariatur. Excepteur sint 
occaecat cupidatat non proident, sunt in 
culpa qui officia deserunt mollit anim id est laborum.'''

#obliczenia beda wykonane niezaleznie na zdaniach (rozdzielonych kropkami)
zdania = lorem_ipsum.split('.')

#wykonujemy zadanie policz_litery na poszczegolnych zdaniach (mapowanie)
pulaworkerow = multiprocessing.Pool()
policzone_zdaniami = pulaworkerow.map(policz_litery,zdania)

#redukujemy otrzymane wyniki czesciowe przy pomocy funkcji polacz_slowniki
zredukowane = reduce(polacz_slowniki,policzone_zdaniami)
print(zredukowane)

Przeszukiwanie katalogów

Przeszukiwanie katalogów w Python

Jedną z zalet Python-a jest jego wieloplatformowość. Bardzo często da się w tym języku napisać skrypt lub program, który bez zmian będzie działał zarówno na Windowsach, jak i na różnego rodzaju unixo-pochodnych systemach (linuxach, aixach czy solarisach).
Poniższy programik pozwala przejść strukturę katalogów w poszukiwaniu plików których nazwy pasują do zadanego wyrażenia regularnego. Zadanie to łatwo zrobić zarówno w Powershellu, jak i bashu, jednak programik ten łatwo można wykorzystać w większych projektach, w których potrzebujemy przeszukiwać system plików.
Program wykorzystuje funkcję os.walk do trawersowania systemu plików i re.match do dopasowania wzorca. Nie wymaga więc instalowania niczego spoza biblioteki standardowej Pythona. Kolejne znalezione pliki zwracane są przez generator, więc programik nie jest bardzo zasobożerny (przynajmniej w kwestii pamięci).
'''program przechodzący przez katalogi podane w argumencie
w poszukiwaniu plikow pasujacych do wyrazenia regularnego'''
import os
import re
import sys
def przeszukaj_katalogi(katalog_glowny,wzorzec):
    '''funkcja generujaca pliki w oparciu o wzorzec w zadanym katalogu'''
    for katalog,katalogi,pliki in os.walk(katalog_glowny):
        for plik in pliki:
            if re.match(wzorzec,plik):
                yield(katalog+os.sep+plik)

#przyklad uzycia
if __name__=='__main__':
    if len(sys.argv)<2:
        print('podaj wzorzec plikow ktore poszukujesz')
        sys.exit()
    elif len(sys.argv)<3:
        katalogi = ['.']
        wzorzec = sys.argv[1]
    else:
        wzorzec = sys.argv[1]
        katalogi = sys.argv[2:]

    for katalog in katalogi:
        for plik in przeszukaj_katalogi(katalog,wzorzec):
            print(plik)

Obliczanie wartości własnych

Obliczanie wartości własnych i wektorów własnych macierzy w Python

Jednym z pierwszych zastosowań, do których wykorzystywałem języka Python, była praca z dużymi macierzami opisującymi konfiguracje elektronów. Python posiada doskonałą bibliotekę do obliczeń numerycznych - numpy. Praca z macierzami staje się wyjątkowo prosta:) Poniższy program pokazuje, jak obliczyć wartości własne macierzy (numpy.linalg.eigvals) oraz jak obliczyć wartości i wektory własne macierzy (eig).
'''programik oblicza wartosci wlasne (i ewentualnie wektory wlasne) macierzy'''

import numpy as np
#przykladowa macierz (o losowych elementach)
mtx = np.random.rand(1000,1000)

#z bedzie zawieralo wartosci wlasne
z=np.linalg.eigvals(mtx)
#z=np.linalg.eig(mtx)

Jak widać programik jest wyjątkowo prosty i łatwy w zrozumieniu. To, co dzieje się pod spodem wcale nie jest już takie proste.
Uwaga - obliczanie wektorow wlasnych wymaga dodatkowych obliczeń i dostepnej pamieci. Jeśli interesują Cię szczegóły, to zobacz dokumentację silnika numpy, czyli lapacka.

Interakcja ze schowkiem

1 Interakcja ze schowkiem w Windows

Poniżej zamieszczony programik pozwala posortować tekstową zawartość schowka w Windows. Jest prostym przykładem komunikacji ze schowkiem.
Wymaga zainstalowania biblioteki win32clipboard, dostarczanej razem z pywin32.
import win32clipboard
win32clipboard.OpenClipboard()
clipboard_data = win32clipboard.GetClipboardData()

sorted_data = '\n'.join(sorted(clipboard_data.splitlines()))

win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(sorted_data)
win32clipboard.CloseClipboard()