• Nie Znaleziono Wyników

SQLAlchemy SQL Toolkit i ORM to zestaw narzędzi do pracy z bazami danych. SQLAlchemy

N/A
N/A
Protected

Academic year: 2021

Share "SQLAlchemy SQL Toolkit i ORM to zestaw narzędzi do pracy z bazami danych. SQLAlchemy"

Copied!
135
0
0

Pełen tekst

(1)

SQLAlchemy

SQLAlchemy SQL Toolkit i ORM to zestaw narzędzi do pracy z bazami danych.

(2)

SQLAlchemy

(3)

SQLAlchemy

SQLAlchemy Core skupia się na schemacie bazy danych, zaś SQLAlchemy ORM na modelu

relacyjnej bazy danych, który odwzorowuje ten schemat.

(4)

SQLAlchemy

Wpiera te bazy przez pakiety:

Postgres: psycopg2 SQLite: pysqlite MySQL: MySQLDB

Oracle: cx_Oracle

MS-SQL: adodbapi pymssql Firebird: kinterbasdb

(5)

Instalacja

sudo apt­get install postgresql

sudo apt­get install python­sqlalchemy sudu apt­get install python­migrate

sudo apt­get install python­psycopg2 sudo apt­get install pgadmin3

xhost +local:

# sudo passwd postgres

# new password: postgres

# re: postgres sudo su postgres

createuser ­P dbstep createdb dbstepy

pgadmin3

Nowe połączenie: dbstepy | localhost | 5432 |  postgres | dbstep | dbstep  

(6)

Instalacja

Sprawdzenie instalacji:

Sprawdzenie instalacji:

import sqlalchemy import sqlalchemy

sqlalchemy.__version__

sqlalchemy.__version__  

(7)

Połączenie

Najpierw należy stworzyć silnik Najpierw należy stworzyć silnik::

from sqlalchemy import * from sqlalchemy import *

sqlalchemy.create_engine(*args,  sqlalchemy.create_engine(*args, 

**kwargs)

**kwargs)

Łańcuch dostępu do bazy (

Łańcuch dostępu do bazy (argsargs):):  

dialect+driver://user:password@ho dialect+driver://user:password@ho

st/dbname[?key=value..]

st/dbname[?key=value..]

dialect to np.

dialect to np.

mysql, oracle, postgresql mysql, oracle, postgresql

driver nazwa DBAPI:

driver nazwa DBAPI:

psycopg2, pyodbc, cx_oracle

psycopg2, pyodbc, cx_oracle, itd., itd.

  

(8)

Połączenie

Dla postgresa Dla postgresa::

# default

# default engine =  engine = 

create_engine(’postgresql://scott create_engine(’postgresql://scott

:tiger@localhost/mydatabase’) :tiger@localhost/mydatabase’)

# psycopg2

# psycopg2 engine =  engine = 

create_engine(’postgresql+psycopg create_engine(’postgresql+psycopg 2://scott:tiger@localhost/mydatab 2://scott:tiger@localhost/mydatab

ase’) ase’)

  

(9)

Połączenie

Dla postgresa Dla postgresa::

# pg8000

# pg8000 engine =  engine = 

create_engine(’postgresql+pg8000:

create_engine(’postgresql+pg8000:

//scott:tiger@localhost/mydatabas //scott:tiger@localhost/mydatabas e’)e’)

# Jython

# Jython engine =  engine = 

create_engine(’postgresql+zxjdbc:

create_engine(’postgresql+zxjdbc:

//scott:tiger@localhost/mydatabas //scott:tiger@localhost/mydatabas e’)e’)

  

(10)

Połączenie

kwargs odpowiada za specyficzne parametry odpowiada za specyficzne parametry dla dialektu, bazy danych, itp.

dla dialektu, bazy danych, itp.:: echo=False –

echo=False – logowanie poleceń na stdout logowanie poleceń na stdout encoding='utf­8' –

encoding='utf­8' – domyślne kodowanie domyślne kodowanie znaków, łańcuchy tak kodowane wyświetlane znaków, łańcuchy tak kodowane wyświetlane

są jako

są jako u'łańcuch' u'łańcuch'

convert_unicode=False –

convert_unicode=False – domyślne domyślne konwertowanie łańcuchów z bazie na unicode konwertowanie łańcuchów z bazie na unicode

execution_options –

execution_options – w tym m.in. w tym m.in.

autocommit autocommit

  

(11)

Połączenie

kwargs odpowiada za specyficzne parametry odpowiada za specyficzne parametry dla dialektu, bazy danych, itp.

dla dialektu, bazy danych, itp.:: listeners –

listeners – listenery na zdarzenia listenery na zdarzenia związane z pulą połączeń

związane z pulą połączeń

Dostępnych jest wiele innych parametrów.

Dostępnych jest wiele innych parametrów.

Przykład Przykład

pg_db =  pg_db = 

create_engine('postgres://dbstep:

create_engine('postgres://dbstep:

dbstep@localhost:5433/dbstepy') dbstep@localhost:5433/dbstepy')  

Najczęściej domyślny port to

Najczęściej domyślny port to 54325432..

(12)

Połączenie

pg_db jest to teraz jest to teraz EngineEngine. Posiada on wiele . Posiada on wiele metod

metod::

begin – 

begin – zwracająca kontekstzwracająca kontekst connect – 

connect – zwracająca połączeniezwracająca połączenie execute – 

execute – wykonująca poleceniewykonująca polecenie table_names – 

table_names – zwracająca dostępne tabele zwracająca dostępne tabele w bazie

w bazie

transaction – 

transaction –  opakowująca funkcję w opakowująca funkcję w transakcję

transakcję

Przestarzałe

Przestarzałe create, drop create, drop (teraz należy używać (teraz należy używać Table.create(), Index.drop(), 

MetaData.create_all()))

(13)

Połączenie

Sprawdźmy działanie połączenia:

Sprawdźmy działanie połączenia:

Przykład Przykład  

print pg_db.execute("select  print pg_db.execute("select 

1").scalar() 1").scalar()

Bez połączenia select nie wykonałby się.

Bez połączenia select nie wykonałby się.

(14)

MetaData

Tabela z informacją o tabelach. Klasę Tabela z informacją o tabelach. Klasę

powiązaną z nią przez użytkownika nazywamy powiązaną z nią przez użytkownika nazywamy

Mapperem.

Mapperem.

Zatem klasyczne powiązanie wygląda tak:

Zatem klasyczne powiązanie wygląda tak:

MetaData – obiekt a na MetaData – klasa A MetaData – obiekt a na MetaData – klasa A

pythona + mapper(A,a).

pythona + mapper(A,a).

(15)

Mapowanie

Mając połączenie z bazą danych możemy Mając połączenie z bazą danych możemy

przystąpić do mapowania bazy danych na klasy.

przystąpić do mapowania bazy danych na klasy.

Aby do tego przystąpić musimy mieć bazę Aby do tego przystąpić musimy mieć bazę

deklaratywną.

deklaratywną.

Przykład Przykład

from sqlalchemy.ext.declarative  from sqlalchemy.ext.declarative 

import declarative_base import declarative_base

Baza = declarative_base() Baza = declarative_base()

Po niej będziemy nasze klasy dziedziczyć.

Po niej będziemy nasze klasy dziedziczyć.

(16)

Mapowanie

Można ją parametryzować, np.

Można ją parametryzować, np.

metadata

metadata – powoduje współdzielenie MetaData – powoduje współdzielenie MetaData z innymi bazami

z innymi bazami

Ma też atrybuty i metody, np.:

Ma też atrybuty i metody, np.:

__tablename__

__tablename__  - nazwa tabeli- nazwa tabeli __init__

__init__  - konstruktor, metoda no-op- konstruktor, metoda no-op __repr__

__repr__ - jaka ma być odpowiedź na żądanie - jaka ma być odpowiedź na żądanie wyświetlenia obiektu

wyświetlenia obiektu

Stwórzmy kilka typowych klas.

Stwórzmy kilka typowych klas.

Przykład Przykład

from sqlalchemy import * from sqlalchemy import *

# Column, Integer, String

# Column, Integer, String

(17)

Tworzenie klas

Przykład Przykład

class Uzytkownik(Baza):

class Uzytkownik(Baza):

        __tablename__ = 'uzytkownicy' __tablename__ = 'uzytkownicy'          id = Column(Integer, id = Column(Integer, 

primary_key = True) primary_key = True)

        imie = Column(String(50))imie = Column(String(50))         nazwisko = nazwisko = 

Column(String(100)) Column(String(100))

        haslo = Column(String(100))haslo = Column(String(100))

        zalogowany = Column(Boolean, zalogowany = Column(Boolean,  default=False)

default=False)

(18)

Tworzenie klas

#opcjonalne

#opcjonalne

        def __init__(self, imie, def __init__(self, imie,  nazwisko, haslo):

nazwisko, haslo):

        

        self.imie = imieself.imie = imie         

        self.nazwisko = nazwiskoself.nazwisko = nazwisko         

        self.haslo = haslo      self.haslo = haslo               def __repr__(self):def __repr__(self):

        

        return return 

"<Uzytkownik('%s','%s','%s','%s')

"<Uzytkownik('%s','%s','%s','%s')

>" % (self.imie, self.nazwisko, 

>" % (self.imie, self.nazwisko,  self.haslo, self.zalogowany)

self.haslo, self.zalogowany)         def zaloguj_sie(self):def zaloguj_sie(self):

        

        self.zalogowany=Trueself.zalogowany=True

(19)

Tworzenie klas

Metody, jakie można przedeklarować lub używać:

Metody, jakie można przedeklarować lub używać:

append_column

append_column – dodaje kolumnę, ale tylko do – dodaje kolumnę, ale tylko do klasy – nie zmienia schematu bazy

klasy – nie zmienia schematu bazy create

create – tworzy – tworzy dropdrop – usuwa – usuwa

exists

exists – sprawdza istnienie – sprawdza istnienie itd.itd.

(20)

Tworzenie klas

Podobnie przy tworzeniu tej klasy możemy Podobnie przy tworzeniu tej klasy możemy

parametryzować jej użycie:

parametryzować jej użycie:

namename – inna nazwa tabeli w bazie – inna nazwa tabeli w bazie

Są również parametry związane z automatycznym Są również parametry związane z automatycznym

wczytywaniem wartości z bazy, czy listenery.

wczytywaniem wartości z bazy, czy listenery.

(21)

Tworzenie tabel

Po stworzeniu modelu bazy danych, możemy Po stworzeniu modelu bazy danych, możemy

utworzyć na jej podstawie schemat.

utworzyć na jej podstawie schemat.

Przykład Przykład

Baza.metadata.create_all(pg_db) Baza.metadata.create_all(pg_db)

Sprawdźmy, jak wygląda:

Sprawdźmy, jak wygląda:

pgadmin3 pgadmin3

(22)

Tworzenie instancji

Przykład Przykład

zwirek = Uzytkownik('Antoni',  zwirek = Uzytkownik('Antoni', 

'Zwirek', 'zwirek123') 'Zwirek', 'zwirek123')

muchomorek = Uzytkownik('Albert',  muchomorek = Uzytkownik('Albert', 

'Muchomorek', 'mucha123') 'Muchomorek', 'mucha123')

wodnik = Uzytkownik(imie =  wodnik = Uzytkownik(imie = 

'Wodnik', nazwisko='Szuwarek',  'Wodnik', nazwisko='Szuwarek', 

haslo='bulbul123') haslo='bulbul123')

print zwirek print zwirek

print muchomorek print muchomorek

print wodnik print wodnik

print str(muchomorek.id) print str(muchomorek.id)  

(23)

Sesja

Ostatnie polecenie pokazuje, że id jest None.

Ostatnie polecenie pokazuje, że id jest None.

Oznacza to tyle, że jeszcze nie zostało zapisane w Oznacza to tyle, że jeszcze nie zostało zapisane w bazie – sekwencja, która powstaje dla primary key bazie – sekwencja, która powstaje dla primary key

w postgresie, nie została jeszcze wykonana dla w postgresie, nie została jeszcze wykonana dla

tego obiektu.

tego obiektu.

Możemy przesłać obiekt do bazy (jako wiersz) Możemy przesłać obiekt do bazy (jako wiersz)

dopiero w sesji.

dopiero w sesji.

(24)

Sesja

Przykład Przykład

Sesja = sessionmaker(bind =  Sesja = sessionmaker(bind = 

pg_db) pg_db)

#Sesja = sessionmaker()

#Sesja = sessionmaker()

#Sesja.configure(bind = pg_db)

#Sesja.configure(bind = pg_db) sesja = Sesja()

sesja = Sesja() sesja

sesja typu typu SessionSession zapamiętuje szczegóły zapamiętuje szczegóły połączenia z klientem.

połączenia z klientem.

sessionmaker

sessionmaker tworzy obiekt, która pozwala na tworzy obiekt, która pozwala na pobranie/stworzenie instancji klasy Session w pobranie/stworzenie instancji klasy Session w

dowolnym miejscu.

dowolnym miejscu.

(25)

Sesja

W sesji znajdują się unikalni reprezentanci W sesji znajdują się unikalni reprezentanci

obiektów z bazy danych (strukura

obiektów z bazy danych (strukura IdentityMapIdentityMap), a ), a wszystkie zmiany są „wstrzymywane”, aż do

wszystkie zmiany są „wstrzymywane”, aż do momentu zatwierdzenia. Po zatwierdzeniu momentu zatwierdzenia. Po zatwierdzeniu

IdentityMap

IdentityMap jest wypełniana na nowo. jest wypełniana na nowo.

(26)

Sesja

Niektóre z dostępnych parametrów sesionmaker:

Niektóre z dostępnych parametrów sesionmaker:

autoflush

autoflush – natychmiastowe zmiany (ale nie – natychmiastowe zmiany (ale nie zatwierdzone), bez oczekiwania na taką

zatwierdzone), bez oczekiwania na taką

konieczność (np. mimo braku odczytu z bazy) – konieczność (np. mimo braku odczytu z bazy) –

na końcu wystarczy

na końcu wystarczy commit()commit() zatwierdzający zatwierdzający autocommit

autocommit – natychmiastowe zatwierdzanie – natychmiastowe zatwierdzanie zmian w odrębnych chwilowych transakcjach

zmian w odrębnych chwilowych transakcjach expire_on_commit

expire_on_commit – wygasza sesję po – wygasza sesję po zatwierdzeniu zmian – domyślne,

zatwierdzeniu zmian – domyślne,

bindbind – powiązanie sesji z konkretnym – powiązanie sesji z konkretnym połączeniem

połączeniem

(27)

Sesja

Niektóre z metod

Niektóre z metod SessionSession::

add add - dodaje obiekt do sesji- dodaje obiekt do sesji add_all 

add_all - dodaje kolekcję obiektów do sesji- dodaje kolekcję obiektów do sesji begin

begin – początek transakcji – początek transakcji begin_nested

begin_nested – początek transakcji – początek transakcji zagnieżdżonej

zagnieżdżonej commit

commit – zatwierdzenie zmian – zatwierdzenie zmian dirty

dirty – obiekty zmienione – obiekty zmienione newnew – obiekty nowe – obiekty nowe

(28)

Sesja

execute

execute - wykonanie polecenia - wykonanie polecenia flush

flush - zapis zmian, ale jeszcze nie - zapis zmian, ale jeszcze nie zatwierdzony

zatwierdzony query

query – zapytanie – zapytanie rollback

rollback – wycofanie się z zapisanych zmian – wycofanie się z zapisanych zmian scalar

scalar – jak – jak executeexecute, ale z liczbą w wyniku, ale z liczbą w wyniku

(29)

Transakcja

Jednostka kontaktu z bazą.

Jednostka kontaktu z bazą.

(30)

Stany obiektów

- - transienttransient - instancja nie znajduje się w sesji i nie - instancja nie znajduje się w sesji i nie jest zapisana w bazie, jedyne powiązanie to takie, jest zapisana w bazie, jedyne powiązanie to takie,

że klasa ma powiązany

że klasa ma powiązany mapper()mapper()

- - pendingpending - po - po add()add(), jest w sesji, ale nie jest , jest w sesji, ale nie jest zapisana w bazie aż do

zapisana w bazie aż do flush()flush()

- - persistentpersistent - instancja jest w sesji i w bazie - instancja jest w sesji i w bazie

- - detacheddetached - jest w bazie, ale nie ma jej w żadnej - jest w bazie, ale nie ma jej w żadnej sesji. To normalny stan, z tym wyjątkiem, że nie sesji. To normalny stan, z tym wyjątkiem, że nie

ma możliwości wykonania żadnego SQLa w celu ma możliwości wykonania żadnego SQLa w celu

pobrania kolekcji lub atrybutów, które nie są już pobrania kolekcji lub atrybutów, które nie są już

załadowane lub ustawione na ``

załadowane lub ustawione na ``expiredexpired''.''.

(31)

Tworzenie obiektów

Na bazie naszego przykładu, po

Na bazie naszego przykładu, po add()add() mamy mamy obiekty „w sesji”. Wszystkie są „

obiekty „w sesji”. Wszystkie są „pendingpending”, ale ”, ale jeszcze nie „

jeszcze nie „persistedpersisted”.”.

Przykład Przykład

zwirek_persisted =  zwirek_persisted = 

sesja.query(Uzytkownik).filter_by sesja.query(Uzytkownik).filter_by

(nazwisko='Zwirek').first() (nazwisko='Zwirek').first()

print str(zwirek.id) print str(zwirek.id)

print str(zwirek_persisted.id) print str(zwirek_persisted.id)

Teraz już zmiany zostały zatwierdzone w bazie – Teraz już zmiany zostały zatwierdzone w bazie –

mają id. Można to zrobić również przez

mają id. Można to zrobić również przez flush()flush()..

(32)

Rollback

print  print 

sesja.query(Uzytkownik).count() sesja.query(Uzytkownik).count()

Wycofujemy zmiany:

Wycofujemy zmiany:

print sesja.rollback() print sesja.rollback()

print  print 

sesja.query(Uzytkownik).count() sesja.query(Uzytkownik).count()

(33)

Zapytania

sesja.add_all([Uzytkownik('Dzoana sesja.add_all([Uzytkownik('Dzoana

','Krupa','tapmadl'),       ','Krupa','tapmadl'),      

Uzytkownik('Shakira','Ripoll',Non Uzytkownik('Shakira','Ripoll',Non e), e), 

Uzytkownik('Grzegorz','Markowski' Uzytkownik('Grzegorz','Markowski'

, 'perfect123')]) , 'perfect123')])

print  print 

sesja.query(Uzytkownik).filter_by sesja.query(Uzytkownik).filter_by (nazwisko='Markowski').first().id (nazwisko='Markowski').first().id  

(34)

Zapytania -filtrowanie

query()

query() zwraca obiekt zwraca obiekt QueryQuery. Metody:. Metody:

add_column, add_columns 

add_column, add_columns - dodaje - dodaje kolumnę do wynikowych kolumn

kolumnę do wynikowych kolumn

allall  - zwraca listę obiektów tej klasy- zwraca listę obiektów tej klasy as_scalar 

as_scalar - zmiana pełnego selekta na - zmiana pełnego selekta na

podselekta zwracającego jedną wartość liczbową podselekta zwracającego jedną wartość liczbową

autoflush

autoflush - dla tego zapytania można - dla tego zapytania można wstrzymać

wstrzymać flushflush

column_description

column_description - wynik razem z - wynik razem z opisem kolumn

opisem kolumn count

count - zlicza liczbę wierszy - zlicza liczbę wierszy

(35)

Zapytania -filtrowanie

distinct

distinct - metoda ukrywająca powtarzające - metoda ukrywająca powtarzające się (pod jakimś względem) wiersze

się (pod jakimś względem) wiersze delete

delete - usuwa wyszukane wiersze z - usuwa wyszukane wiersze z bazy/modelu, zwraca liczbę usuniętych, z bazy/modelu, zwraca liczbę usuniętych, z

pominięciem kaskad pominięciem kaskad

except_ 

except_ ii except_all except_all - pozwala odsiać - pozwala odsiać część wyników poprzez podzapytanie

część wyników poprzez podzapytanie filter

filter - filtruje po warunku dla dokładnie - filtruje po warunku dla dokładnie określonego pola

określonego pola filter_by

filter_by – filtrowanie po wskazanym kluczu – filtrowanie po wskazanym kluczu

(36)

Zapytania -filtrowanie

first

first - zwraca pierwszy obiekt wśród - zwraca pierwszy obiekt wśród pasujących do wyszukiwania

pasujących do wyszukiwania from_statement

from_statement – wykonuje podane – wykonuje podane zapytanie

zapytanie

getget – zwraca obiekt o podanym primary key – zwraca obiekt o podanym primary key group_by, having

group_by, having – elementy SQL, zgodnie – elementy SQL, zgodnie ze standardem

ze standardem

oneone - zwraca jeden obiekt pasujący, jeśli jest ich - zwraca jeden obiekt pasujący, jeśli jest ich więcej lub nie ma żadnego - zwraca błąd

więcej lub nie ma żadnego - zwraca błąd MultipleResultsFound

MultipleResultsFound lub lub NoResultFoundNoResultFound

(37)

Zapytania -filtrowanie

union, union_all 

union, union_all - pozwala dołączyć - pozwala dołączyć nowe lub dodatkowe z drugiego zapytania

nowe lub dodatkowe z drugiego zapytania intersect, intersect_all

intersect, intersect_all – przecięcie – przecięcie joinjoin – złączenie, razem z filter – złączenie, razem z filter

label 

label – zmiana nagłówka kolumny– zmiana nagłówka kolumny limit

limit – ogranicza liczbę wyników – ogranicza liczbę wyników order_by

order_by – porządkuje – porządkuje outerjoin

outerjoin – złączenie lewostronne – złączenie lewostronne statement

statement – polecenie sql, które reprezentuje – polecenie sql, które reprezentuje to Query

to Query update

update – zmienia wartości – zmienia wartości

(38)

Relacje

Związki między tabelami poprzez klucze obce Związki między tabelami poprzez klucze obce

mogą mieć postać

mogą mieć postać jeden-do-wielujeden-do-wielu, , wiele-do-wiele-do- jednego

jednego, , jeden-do-jednegojeden-do-jednego i i wiele-do-wieluwiele-do-wielu

(realizacja poprzez odrębną tabelę i dwie relacje:

(realizacja poprzez odrębną tabelę i dwie relacje:

jeden-do wielu

jeden-do wielu i i wiele-do-jednegowiele-do-jednego))

(39)

Relacje: jeden-do-wielu

Klucz obcy jest w klasie „wiele”.

Klucz obcy jest w klasie „wiele”.

Przykład Przykład

from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey

from sqlalchemy.orm import relationship, backref from sqlalchemy.orm import relationship, backref

class Kategorie(Baza):

class Kategorie(Baza):

__tablename__ = 'kategorie'__tablename__ = 'kategorie'

id = Column(Integer,primary_key = True)id = Column(Integer,primary_key = True) czasopisma = relationship("Czasopisma")czasopisma = relationship("Czasopisma") nazwa = Column(String(100))nazwa = Column(String(100))

def __init__ (self, nazwa):def __init__ (self, nazwa):

self.nazwa = nazwaself.nazwa = nazwa

(40)

Relacje: jeden-do-wielu

class Czasopisma(Baza):

class Czasopisma(Baza):

__tablename__ = 'czasopisma'__tablename__ = 'czasopisma'

id = Column(Integer,primary_key = True)id = Column(Integer,primary_key = True) nazwa = Column(String(100))nazwa = Column(String(100))

id_kat = id_kat =

Column(Integer,ForeignKey("kategorie.id")) Column(Integer,ForeignKey("kategorie.id")) kategoria = relationship("Kategorie", kategoria = relationship("Kategorie",

backref=backref('czasopisma',order_by=id)) backref=backref('czasopisma',order_by=id)) def __init__ (self, nazwa):def __init__ (self, nazwa):

self.nazwa = nazwaself.nazwa = nazwa

(41)

Relacje: wiele-do-jednego

class Czasopisma(Baza):

class Czasopisma(Baza):

__tablename__ = 'czasopisma'__tablename__ = 'czasopisma'

id = Column(Integer,primary_key = True)id = Column(Integer,primary_key = True) nazwa = Column(String(100))nazwa = Column(String(100))

id_kat = id_kat =

Column(Integer,ForeignKey('kategorie.id')) Column(Integer,ForeignKey('kategorie.id')) wydanie_id = Column(Integer, wydanie_id = Column(Integer,

ForeignKey('wydania.id')) ForeignKey('wydania.id'))

wydania = relationship("Wydania", wydania = relationship("Wydania", backref="czasopismo")

backref="czasopismo")

def __init__ (self, nazwa):def __init__ (self, nazwa):

self.nazwa = nazwaself.nazwa = nazwa

(42)

Relacje: wiele-do-jednego

class Wydania(Baza):

class Wydania(Baza):

__tablename__ = 'wydania'__tablename__ = 'wydania'

id = Column(Integer, primary_key=True)id = Column(Integer, primary_key=True) issue = Column(String(100))issue = Column(String(100))

(43)

Relacje: jeden-do-jednego

class Autorzy(Baza):

class Autorzy(Baza):

__tablename__ = 'autorzy'__tablename__ = 'autorzy'

id = Column(Integer, primary_key = True)id = Column(Integer, primary_key = True) imie = Column(String(100))imie = Column(String(100))

nazwisko = Column(String(100))nazwisko = Column(String(100))

telefon = relationship("Telefony", uselist=False, telefon = relationship("Telefony", uselist=False, backref="autor")

backref="autor")

(44)

Relacje: jeden-do-jednego

#zakladajac, ze ma tylko jeden telefon

#zakladajac, ze ma tylko jeden telefon class Telefony(Baza):

class Telefony(Baza):

__tablename__ = 'telefony'__tablename__ = 'telefony'

id = Column(Integer, primary_key = True)id = Column(Integer, primary_key = True) autor_id = Column(Integer, autor_id = Column(Integer,

ForeignKey('autorzy.id')) ForeignKey('autorzy.id'))

(45)

Relacje: wiele-do-wielu

#wielu autorów ma wiele artykułów

#tablica asocjacyjna – fizycznie tabela na bazie aut_art = Table('aut_art', Baza.metadata,

aut_art = Table('aut_art', Baza.metadata,

Column('autor_id', Integer, Column('autor_id', Integer, ForeignKey('autorzy.id')),

ForeignKey('autorzy.id')),

Column('artykul_id', Integer, Column('artykul_id', Integer, ForeignKey('artykuly.id'))

ForeignKey('artykuly.id')) ))

(46)

Relacje: wiele-do-wielu

class Artykuly(Baza):

class Artykuly(Baza):

__tablename__ = 'artykuly'__tablename__ = 'artykuly'

id = Column(Integer, primary_key = True)id = Column(Integer, primary_key = True) tytul = Column(String(300))tytul = Column(String(300))

abstrakt = Column(String)abstrakt = Column(String)

autorzy = relationship("Autorzy", autorzy = relationship("Autorzy",

secondary=aut_art, backref=”artykuly”) secondary=aut_art, backref=”artykuly”)

(47)

Relacje: wiele-do-wielu

class Autorzy(Baza):

class Autorzy(Baza):

__tablename__ = 'autorzy'__tablename__ = 'autorzy'

id = Column(Integer, primary_key = True)id = Column(Integer, primary_key = True) imie = Column(String(100))imie = Column(String(100))

nazwisko = Column(String(100))nazwisko = Column(String(100))

telefon = relationship("Telefony", uselist=False, telefon = relationship("Telefony", uselist=False, backref="autor")

backref="autor")

(48)

Odwołania do relacyjnych obiektów

kategoria.czasopisma =  kategoria.czasopisma = 

[czasopismo, czas2]

[czasopismo, czas2]  

print kategoria.czasopisma print kategoria.czasopisma

for c in kategoria.czasopisma:

for c in kategoria.czasopisma:

        print '­­­­ ', c.id, c.nazwa print '­­­­ ', c.id, c.nazwa 

(49)

Zapytania z relacjami

print sesja.query(Czasopisma,  print sesja.query(Czasopisma, 

Kategorie).join(Kategorie) Kategorie).join(Kategorie)

for c, k in  for c, k in 

sesja.query(Czasopisma,  sesja.query(Czasopisma, 

Kategorie).join(Kategorie).all():

Kategorie).join(Kategorie).all():

        print c.id, c.nazwa, print c.id, c.nazwa,  c.id_kat, k.nazwa

c.id_kat, k.nazwa  

(50)

Zapytania z relacjami

a_alias = aliased(Czasopisma) a_alias = aliased(Czasopisma)

q = sesja.query(Kategorie).\

q = sesja.query(Kategorie).\

join(Kategorie.czasopisma).\

join(Kategorie.czasopisma).\

join(a_alias,  join(a_alias, 

Kategorie.czasopisma).\

Kategorie.czasopisma).\

filter(Czasopisma.nazwa=='JDBalan filter(Czasopisma.nazwa=='JDBalan

ce').\

ce').\

filter(a_alias.nazwa=='Journal  filter(a_alias.nazwa=='Journal  of')of')

print q print q

for t in q.all():

for t in q.all():

        print t.id, t.nazwaprint t.id, t.nazwa  

(51)

Lazy i Eager Loading

Lazy Loading

Lazy Loading – domyślne „leniwe” pobieranie – domyślne „leniwe” pobieranie obiektów

obiektów

kategorie.czasopisma kategorie.czasopisma

Gdy chcemy wyświetlić wartość tego pola, Gdy chcemy wyświetlić wartość tego pola,

wówczas dopiero dokonuje się pobranie obiektów wówczas dopiero dokonuje się pobranie obiektów

z bazy, mimo że operowaliśmy już na obiekcie z bazy, mimo że operowaliśmy już na obiekcie

kategorie kategorie

Eager Loading

Eager Loading – „chciwe” pobieranie obiektów. – „chciwe” pobieranie obiektów.

W takim przypadki czasopisma pobrane byłyby W takim przypadki czasopisma pobrane byłyby

od razu przy pobieraniu obiektu kategorie.

od razu przy pobieraniu obiektu kategorie.

(52)

Lazy i Eager Loading

jan =  jan = 

sesja.add(Autorzy(imie='Jan',  sesja.add(Autorzy(imie='Jan', 

nazwisko='Niejan')) nazwisko='Niejan'))

michal =  michal = 

sesja.add(Autorzy(imie='Michal',  sesja.add(Autorzy(imie='Michal', 

nazwisko='Niejan')) nazwisko='Niejan'))

artjana =  artjana = 

sesja.add(Artykuly('Pewien',  sesja.add(Artykuly('Pewien', 

'Test', [jan])) 'Test', [jan]))

artjana2 =  artjana2 = 

sesja.add(Artykuly('Pewien  sesja.add(Artykuly('Pewien 

Drugi', 'Test', [jan, michal]))  Drugi', 'Test', [jan, michal])) 

(53)

Lazy i Eager Loading

from sqlalchemy.orm import  from sqlalchemy.orm import 

joinedload, subqueryload,  joinedload, subqueryload, 

lazyload lazyload

samjan = sesja.query(Autorzy).\

samjan = sesja.query(Autorzy).\

        filter_by(imie='Jan')filter_by(imie='Jan')

janart = sesja.query(Autorzy).\

janart = sesja.query(Autorzy).\

        

options(joinedload('artykuly')).\

options(joinedload('artykuly')).\

        filter_by(imie='Jan')filter_by(imie='Jan') print samjan

print samjan print janart print janart

(54)

Lazy i Eager Loading

SELECT autorzy.id AS autorzy_id,  SELECT autorzy.id AS autorzy_id, 

autorzy.imie AS autorzy_imie,  autorzy.imie AS autorzy_imie, 

autorzy.nazwisko AS  autorzy.nazwisko AS 

autorzy_nazwisko  autorzy_nazwisko 

FROM autorzy  FROM autorzy 

WHERE autorzy.imie = :imie_1 WHERE autorzy.imie = :imie_1

(55)

Lazy i Eager Loading

SELECT autorzy.id AS autorzy_id,  SELECT autorzy.id AS autorzy_id, 

autorzy.imie AS autorzy_imie,  autorzy.imie AS autorzy_imie, 

autorzy.nazwisko AS autorzy_nazwisko,  autorzy.nazwisko AS autorzy_nazwisko, 

artykuly_1.id AS artykuly_1_id,  artykuly_1.id AS artykuly_1_id, 

artykuly_1.tytul AS artykuly_1_tytul,  artykuly_1.tytul AS artykuly_1_tytul, 

artykuly_1.abstrakt AS  artykuly_1.abstrakt AS 

artykuly_1_abstrakt  artykuly_1_abstrakt 

FROM autorzy LEFT OUTER JOIN aut_art AS  FROM autorzy LEFT OUTER JOIN aut_art AS 

aut_art_1 ON autorzy.id =  aut_art_1 ON autorzy.id = 

aut_art_1.autor_id LEFT OUTER JOIN  aut_art_1.autor_id LEFT OUTER JOIN 

artykuly AS artykuly_1 ON artykuly_1.id =  artykuly AS artykuly_1 ON artykuly_1.id = 

aut_art_1.artykul_id  aut_art_1.artykul_id 

WHERE autorzy.imie = :imie_1 WHERE autorzy.imie = :imie_1

(56)

Lazy i Eager Loading

Można również pobierać te dodatkowe obiekty Można również pobierać te dodatkowe obiekty

przez podzapytania.

przez podzapytania.

Domyślne pobieranie zmieniamy w

Domyślne pobieranie zmieniamy w relationshiprelationship::

relationship("Czasopisma",  relationship("Czasopisma",  lazy='joined')

lazy='joined')

relationship("Czasopisma",  relationship("Czasopisma",  lazy='subquery')

lazy='subquery')

Głębsze wnikanie w obiekty odbywa się Głębsze wnikanie w obiekty odbywa się

klasycznie:

klasycznie:

joinedload('autorzy.telefony') joinedload('autorzy.telefony')

A szersze, np.:

A szersze, np.: lazyload('*')lazyload('*')

Lub wybiórczo względem deklaracji:

Lub wybiórczo względem deklaracji:

lazyload('select') lazyload('select')

(57)

Zdarzenia

Możemy dodefiniować też zdarzenia, które Możemy dodefiniować też zdarzenia, które

wyzwalają się w zależności od określonych przez wyzwalają się w zależności od określonych przez

nas zmian.

nas zmian.

Przykład Przykład

artjana = Artykuly('Pewien',  artjana = Artykuly('Pewien', 

'Test', [jan]) 'Test', [jan])

sesja.add(artjana) sesja.add(artjana)  

(58)

Zdarzenia

from sqlalchemy import event from sqlalchemy import event def obserwator(obserwowany,  def obserwator(obserwowany, 

wartosc, starawartosc,  wartosc, starawartosc, 

wyzwalacz):

wyzwalacz):

        print "cos sie stalo z %s" % print "cos sie stalo z %s" %  obserwowany

obserwowany

event.listen(Artykuly.abstrakt,  event.listen(Artykuly.abstrakt, 

'set', obserwator, retval=True) 'set', obserwator, retval=True)

print artjana print artjana

artjana.abstrakt = "inny test"

artjana.abstrakt = "inny test"  

(59)

SQLAlchemy Core

Ta część SQLAlchemy oferuje możliwość Ta część SQLAlchemy oferuje możliwość

budowania bazy danych na podstawie schematu.

budowania bazy danych na podstawie schematu.

Podejście i sposób tworzenia tabel może się Podejście i sposób tworzenia tabel może się

wydawać podobny, ale samo podejście jest wydawać podobny, ale samo podejście jest

zupełnie inne. ORM służy do modelowania, zaś zupełnie inne. ORM służy do modelowania, zaś Core jedynie do tworzenia tabel, powiązań, itp., Core jedynie do tworzenia tabel, powiązań, itp.,

na podstawie schematu.

na podstawie schematu.

Ze względu na większą „niskopoziomowość”

Ze względu na większą „niskopoziomowość”

Core, dalsza część będzie jedynie przeglądem Core, dalsza część będzie jedynie przeglądem

ciekawszych możliwości.

ciekawszych możliwości.

(60)

Dostęp do tabel

for t in metadata.sorted_tables:

for t in metadata.sorted_tables:

print t.name print t.name

(61)

Tworzenie tabel

engine =  engine = 

create_engine(’sqlite:///:memory:

create_engine(’sqlite:///:memory:

’)’)

metadata = MetaData() metadata = MetaData()

user = Table(’user’, metadata, user = Table(’user’, metadata,

Column(’user_id’, Integer,  Column(’user_id’, Integer, 

primary_key = True), primary_key = True),

Column(’user_name’, String(16),  Column(’user_name’, String(16), 

nullable = False), nullable = False),

Column(’email_address’,  Column(’email_address’, 

String(60), key=’email’), String(60), key=’email’),

Column(’password’, String(20),  Column(’password’, String(20), 

nullable = False)) nullable = False))

(62)

Tworzenie tabel

user_prefs = Table(’user_prefs’,  user_prefs = Table(’user_prefs’, 

metadata, metadata,

Column(’pref_id’, Integer,  Column(’pref_id’, Integer, 

primary_key=True), primary_key=True),

Column(’user_id’, Integer,  Column(’user_id’, Integer, 

ForeignKey("user.user_id"),  ForeignKey("user.user_id"), 

nullable=False), nullable=False),

Column(’pref_name’, String(40),  Column(’pref_name’, String(40), 

nullable=False), nullable=False),

Column(’pref_value’, String(100)) Column(’pref_value’, String(100)) ))

metadata.create_all(engine) metadata.create_all(engine)

(63)

Tworzenie i usuwanie tabel

employees.create(engine,  employees.create(engine, 

checkfirst=True) checkfirst=True)

employees.drop(engine,  employees.drop(engine, 

checkfirst=False) checkfirst=False)

(64)

Zmiana schematu tabel

ALTER TABLE

ALTER TABLE poprzez poprzez execute()execute() - czyli - czyli czystym SQLem, albo...

czystym SQLem, albo...

SQLAlchemy-Migrate SQLAlchemy-Migrate

(65)

Triggery

t = Table(’test’, meta, t = Table(’test’, meta,

Column(’abc’, String(20),  Column(’abc’, String(20), 

server_default=FetchedValue()), server_default=FetchedValue()),

Column(’def’, String(20),  Column(’def’, String(20), 

server_onupdate=FetchedValue()) server_onupdate=FetchedValue()) ))

(66)

Sekwencje

table = Table("cartitems", meta, table = Table("cartitems", meta,

Column("cart_id", Integer,  Column("cart_id", Integer, 

Sequence(’cart_id_seq’),  Sequence(’cart_id_seq’), 

primary_key=True), primary_key=True),

Column("description",  Column("description", 

String(40)), String(40)),

Column("createdate", DateTime()) Column("createdate", DateTime()) ))

seq = Sequence(’some_sequence’) seq = Sequence(’some_sequence’)

nextid = connection.execute(seq) nextid = connection.execute(seq)

(67)

Wartości domyślne

Table("mytable", meta, Table("mytable", meta,

Column("somecolumn", Integer,  Column("somecolumn", Integer, 

default=12) default=12) ))

Table("mytable", meta, Table("mytable", meta,

Column("somecolumn", Integer,  Column("somecolumn", Integer, 

onupdate=25) onupdate=25) ))

(68)

Wartości domyślne po stronie SZBD

t = Table(’test’, meta, t = Table(’test’, meta,

Column(’abc’, String(20),  Column(’abc’, String(20), 

server_default=’abc’), server_default=’abc’),

Column(’created_at’, DateTime,  Column(’created_at’, DateTime,  server_default=text("sysdate")) server_default=text("sysdate")) ))

(69)

Inserty

ins =  ins = 

Uzytkownik.insert().values(imie=’

Uzytkownik.insert().values(imie=’

Jack’, nazwisko=’The Ripper’) Jack’, nazwisko=’The Ripper’)

str(ins) str(ins)

result = conn.execute(ins) result = conn.execute(ins)

(70)

Selekty

s = select([Uzytkownik]) s = select([Uzytkownik]) result = conn.execute(s) result = conn.execute(s)

for row in result:

for row in result:

print row print row

(71)

Złączenia

print Kategorie.join(Czasopisma) print Kategorie.join(Czasopisma)

s = select([users.c.fullname],  s = select([users.c.fullname], 

from_obj=[

from_obj=[

users.join(addresses,  users.join(addresses, 

addresses.c.email_address.like(us addresses.c.email_address.like(us

ers.c.name + ’%’)) ers.c.name + ’%’)) ])])

print conn.execute(s).fetchall() print conn.execute(s).fetchall()

również

również outerjoin() outerjoin()

(72)

Parametryzowanie zapytań

from sqlalchemy.sql import  from sqlalchemy.sql import 

bindparam bindparam s = s = 

users.select(users.c.name==bindpa users.select(users.c.name==bindpa

ram(’username’)) ram(’username’)) conn.execute(s,  conn.execute(s, 

username=’wendy’).fetchall() username=’wendy’).fetchall()

(73)

Podpięte funkcje pythona

i = 0 i = 0

def mydefault():

def mydefault():

global i global i

i += 1 i += 1

return i return i

t = Table("mytable", meta, t = Table("mytable", meta,

Column(’id’, Integer, 

Column(’id’, Integer,       primary_key=True, 

primary_key=True,  default=mydefault), default=mydefault),

))

(74)

Funkcje

from sqlalchemy.sql import func from sqlalchemy.sql import func

print func.now() print func.now()

print func.concat(’x’, ’y’) print func.concat(’x’, ’y’)

print  print 

func.xyz_my_goofy_function() func.xyz_my_goofy_function()

print func.current_timestamp() print func.current_timestamp()

print conn.execute(

print conn.execute(

select([func.max(addresses.c.emai select([func.max(addresses.c.emai

l_address,  l_address, 

type_=String).label(’maxemail’)]) type_=String).label(’maxemail’)])   ).scalar()).scalar()

(75)

Unie

from sqlalchemy.sql import union from sqlalchemy.sql import union

u = union(

u = union(

addresses.select(addresses.c.emai addresses.select(addresses.c.emai

l_address==’foo@bar.com’), l_address==’foo@bar.com’),

addresses.select(addresses.c.emai addresses.select(addresses.c.emai

l_address.like(’%@yahoo.com’)), l_address.like(’%@yahoo.com’)),

  ).order_by(addresses.c.email_add).order_by(addresses.c.email_add ress)

ress)

print conn.execute(u).fetchall() print conn.execute(u).fetchall()

podobnie

podobnie intersect, intersect_all,  intersect, intersect_all,  except_all

except_all

(76)

Zliczanie

print conn.execute(select([

print conn.execute(select([

users.c.name, users.c.name,

select([func.count(addresses.c.id select([func.count(addresses.c.id )], )], 

users.c.id==addresses.c.user_id).

users.c.id==addresses.c.user_id).

as_scalar() as_scalar()

])).fetchall() ])).fetchall()

(77)

Podzapytania

s = select([users.c.name],  s = select([users.c.name], 

users.c.id==select([users.c.id]).

users.c.id==select([users.c.id]).

correlate(None)) correlate(None))

print s print s

(78)

Grupowania, having, order by

s = select([addresses.c.user_id,  s = select([addresses.c.user_id, 

func.count(addresses.c.id)]).\

func.count(addresses.c.id)]).\

group_by(addresses.c.user_id).hav group_by(addresses.c.user_id).hav ing(func.count(addresses.c.id)>1) ing(func.count(addresses.c.id)>1)

print conn.execute(s).fetchall() print conn.execute(s).fetchall() s = s = 

select([addresses.c.email_address select([addresses.c.email_address

, addresses.c.id]).distinct().\

, addresses.c.id]).distinct().\

order_by(addresses.c.email_addres order_by(addresses.c.email_addres

s.desc(), addresses.c.id) s.desc(), addresses.c.id)

conn.execute(s).fetchall() conn.execute(s).fetchall()

(79)

Jednoczesne wstawianie do wielu

stmt = users.update().\

stmt = users.update().\

values(name=’ed wood’).\

values(name=’ed wood’).\

where(users.c.id==addresses.c.id) where(users.c.id==addresses.c.id) .\.\

where(addresses.c.email_address.s where(addresses.c.email_address.s

tartswith(’ed%’)) tartswith(’ed%’))

conn.execute(stmt) conn.execute(stmt)

(80)

Usuwanie

conn.execute(users.delete().where conn.execute(users.delete().where

(users.c.name > ’m’)) (users.c.name > ’m’))

(81)

Modelowanie

Encje (leniwe, ale nie anemiczne) Encje (leniwe, ale nie anemiczne)

Obiekty wartości Obiekty wartości

Kontekst Kontekst

(82)

Źródła

Informacje zaczerpnięte z dokumentacji:

Informacje zaczerpnięte z dokumentacji:

http://media.readthedocs.org/pdf/

http://media.readthedocs.org/pdf/

sqlalchemy/latest/sqlalchemy.pdf sqlalchemy/latest/sqlalchemy.pdf

(83)

Komunikacja internetowa

Implementacja komunikacji internetowej i programowanie usług sieciowych

(84)

Gniazda/Socket

Mechanizm Internet Process Communication.

Mechanizm Internet Process Communication.

Służy do dwukierunkowej komunikacji Służy do dwukierunkowej komunikacji

internetowej na niskim poziomie. Charakteryzuje internetowej na niskim poziomie. Charakteryzuje

ją domena adresowa, sposób komunikacji i ją domena adresowa, sposób komunikacji i

protokół sieciowy.

protokół sieciowy.

(85)

Gniazda/Socket

Domeny:

Domeny:

socket.AF_UNIX

socket.AF_UNIX – w obrębie jednej maszyny – w obrębie jednej maszyny socket.AF_INET

socket.AF_INET – po IPv4 – po IPv4 socket.AF_INET6

socket.AF_INET6 – po IPv6 – po IPv6

(86)

Gniazda/Socket

Typy:

Typy:

socket.SOCK_STREAM

socket.SOCK_STREAM – dwukierunkowa, – dwukierunkowa, połączeniowa

połączeniowa

socket.SOCK_DGRAM

socket.SOCK_DGRAM – bezpołączeniowa – bezpołączeniowa korzystająca z datagramów (jednostka danych) korzystająca z datagramów (jednostka danych)

socket.SOCK_RAW

socket.SOCK_RAW – surowe pakiety – surowe pakiety socket.SOCK_RDM

socket.SOCK_RDM - zaufane wiadomości - zaufane wiadomości bezpołączeniowe

bezpołączeniowe

socket.SOCK_SEQPACKET

socket.SOCK_SEQPACKET – zaufane – zaufane wiadomości zorientowane na połączenie wiadomości zorientowane na połączenie

(87)

Gniazda/Socket

Protokoły:

Protokoły:

TCP – połączeniowy TCP – połączeniowy

UDP – bezpołączeniowy UDP – bezpołączeniowy

Często protokoły są wymuszane przez domenę i Często protokoły są wymuszane przez domenę i

typ.

typ.

(88)

Echo

Przykład:

Przykład:

#!/usr/bin/env python

#!/usr/bin/env python from socket import * from socket import *

ip_serwera = "127.0.0.1"

ip_serwera = "127.0.0.1"

port_serwera = 9000 port_serwera = 9000

gniazdo = socket(AF_INET, SOCK_STREAM) gniazdo = socket(AF_INET, SOCK_STREAM)

gniazdo.bind((ip_serwera, port_serwera)) gniazdo.bind((ip_serwera, port_serwera))

gniazdo.listen(1) gniazdo.listen(1)

(89)

Echo

while 1:

while 1:

polaczenie, adres = gniazdo.accept()polaczenie, adres = gniazdo.accept() print "Polaczono", adresprint "Polaczono", adres

while 1:while 1:

dane = polaczenie.recv (1024)dane = polaczenie.recv (1024)

if dane.strip() == "END":if dane.strip() == "END":

polaczenie.close()polaczenie.close()

exit()exit()

else:else:

polaczenie.send (dane)polaczenie.send (dane)

(90)

Echo

Użyteczne narzędzia:

Użyteczne narzędzia:

telnet localhost 9000 telnet localhost 9000

nmap -v localhost nmap -v localhost

fuser -k 9000/tcp fuser -k 9000/tcp

(91)

Architektura Klient-Serwer

Klasyczna architektura sposobu przetwarzania Klasyczna architektura sposobu przetwarzania

informacji.

informacji.

Jedna aplikacja oferuje usługi, druga ich żąda.

Jedna aplikacja oferuje usługi, druga ich żąda.

(92)

Architektura Klient-Serwer

s = socket.socket(

s = socket.socket(

socket.AF_INET, socket.SOCK_STREAM)socket.AF_INET, socket.SOCK_STREAM) s.connect(("umcs.pl", 80))

s.connect(("umcs.pl", 80))

(93)

Architektura Klient-Serwer

serversocket = socket.socket(

serversocket = socket.socket(

socket.AF_INET, socket.SOCK_STREAM)socket.AF_INET, socket.SOCK_STREAM) serversocket.bind((socket.gethostname(), 80)) serversocket.bind((socket.gethostname(), 80))

serversocket.listen(5) serversocket.listen(5)

(94)

Socket

socket.getdefaulttimeout()

socket.getdefaulttimeout() - domyślny timeout w - domyślny timeout w sekundach

sekundach

socket.create_connection(address[, timeout[, socket.create_connection(address[, timeout[,

source_address]]) source_address]])

socket.getaddrinfo(host, port, family=0, socket.getaddrinfo(host, port, family=0,

socktype=0, proto=0, flags=0) socktype=0, proto=0, flags=0)

socket.gethostbyname(hostname)

socket.gethostbyname(hostname) – tłumaczy host – tłumaczy host na IPv4

na IPv4

(95)

Socket

socket.gethostname()

socket.gethostname() - zwraca hostname maszyny, - zwraca hostname maszyny, na której jest uruchomiony

na której jest uruchomiony

socket.gethostbyaddr(ip_address)

socket.gethostbyaddr(ip_address) – zwraca host – zwraca host pod adresem

pod adresem

socket.socket([family[, type[, proto]]])

socket.socket([family[, type[, proto]]]) – zwraca – zwraca gniazdo

gniazdo

(96)

Obiekty typu Socket

socket.accept()

socket.accept() - akceptuje połączenie- akceptuje połączenie socket.bind(address)

socket.bind(address) – podłącza gniazdo do – podłącza gniazdo do (hosta,portu)

(hosta,portu) socket.close()

socket.close() - zamyka połączenie - zamyka połączenie socket.connect(address)

socket.connect(address) – łączy z adresem – łączy z adresem socket.listen(backlog)

socket.listen(backlog) – nakazuje nasłuchiwać – nakazuje nasłuchiwać połączeń w liczbie max. backlog.

połączeń w liczbie max. backlog.

socket.recv(bufsize[, flags])

socket.recv(bufsize[, flags]) – przyjmuje dane – przyjmuje dane wrzucone do gniazda

wrzucone do gniazda

(97)

Obiekty typu Socket

socket.recvfrom(bufsize[, flags])

socket.recvfrom(bufsize[, flags]) – dodatkowo – dodatkowo zwraca adres wysyłającego

zwraca adres wysyłającego socket.send(string[, flags])

socket.send(string[, flags]) – wysyła część danych – wysyła część danych i zwraca ile zostało tych danych przesłanych

i zwraca ile zostało tych danych przesłanych socket.sendall(string[, flags])

socket.sendall(string[, flags]) – wysyła wszystkie – wysyła wszystkie danedane

socket.sendto(string[, flags], address)

socket.sendto(string[, flags], address) – wysyła – wysyła konkretnemu adresatowi

konkretnemu adresatowi socket.settimeout(value)

socket.settimeout(value) – ustawia timeout – ustawia timeout

(98)

Klient i serwer czasu

#!/usr/bin/env python

#!/usr/bin/env python from socket import * from socket import *

import time import time

ip_serwera = "127.0.0.1"

ip_serwera = "127.0.0.1"

port_serwera = 9000 port_serwera = 9000

gniazdo = socket(AF_INET, SOCK_STREAM) gniazdo = socket(AF_INET, SOCK_STREAM)

gniazdo.bind ((ip_serwera, port_serwera)) gniazdo.bind ((ip_serwera, port_serwera))

gniazdo.listen(10) gniazdo.listen(10)

(99)

Klient i serwer czasu

while 1:

while 1:

polaczenie, adres = gniazdo.accept()polaczenie, adres = gniazdo.accept() print "Klient z adresu", adresprint "Klient z adresu", adres

polaczenie.send (time.ctime())polaczenie.send (time.ctime()) polaczenie.close()polaczenie.close()

(100)

Klient i serwer czasu

#!/usr/bin/env python

#!/usr/bin/env python from socket import * from socket import *

import sys import sys

gniazdo = socket (AF_INET, SOCK_STREAM) gniazdo = socket (AF_INET, SOCK_STREAM) gniazdo.connect ((sys.argv[1], int(sys.argv[2]))) gniazdo.connect ((sys.argv[1], int(sys.argv[2])))

czas = gniazdo.recv (1024) czas = gniazdo.recv (1024)

gniazdo.close() gniazdo.close()

print "Czas: ", czas print "Czas: ", czas

(101)

Demony

Demony to aplikacje serwerowe działające w tle.

Demony to aplikacje serwerowe działające w tle.

Mogą oferować usługi lub wykonywać Mogą oferować usługi lub wykonywać

sukcesywnie jakieś zadanie.

sukcesywnie jakieś zadanie.

(102)

Demony

Przykład klasy bazowej demonizującej (źródło:

Przykład klasy bazowej demonizującej (źródło:

http://www.jejik.com/files/examples/daemon.py http://www.jejik.com/files/examples/daemon.py):):

(103)

Demony

#!/usr/bin/env python

#!/usr/bin/env python import sys, time

import sys, time

from sander import Daemon from sander import Daemon class MyDaemon(Daemon):

class MyDaemon(Daemon):

def run(self):def run(self):

i = 0i = 0

while True:while True:

f = open('demon.txt','a')f = open('demon.txt','a') f.write(str(i))f.write(str(i))

i=i+1i=i+1

time.sleep(1)time.sleep(1) f.close()f.close()

(104)

Demony

if __name__ == "__main__":

if __name__ == "__main__":

daemon = MyDaemon('/tmp/daemon-daemon = MyDaemon('/tmp/daemon- example.pid')

example.pid')

if len(sys.argv) == 2:if len(sys.argv) == 2:

if 'start' == sys.argv[1]:if 'start' == sys.argv[1]:

daemon.start()daemon.start()

elif 'stop' == sys.argv[1]:elif 'stop' == sys.argv[1]:

daemon.stop()daemon.stop()

elif 'restart' == sys.argv[1]:elif 'restart' == sys.argv[1]:

daemon.restart()daemon.restart()

(105)

Demony

else:else:

print "Nieznane polecenie"print "Nieznane polecenie"

sys.exit(2)sys.exit(2)

sys.exit(0)sys.exit(0)

else:else:

print "usage: %s start|stop|restart" % print "usage: %s start|stop|restart" % sys.argv[0]

sys.argv[0]

sys.exit(2)sys.exit(2)

(106)

Demony

Dodatkowo można uniezależnić tego demona Dodatkowo można uniezależnić tego demona

nieco od systemu:

nieco od systemu:

if (hasattr(os, "devnull")):

if (hasattr(os, "devnull")):

DEVNULL = os.devnull DEVNULL = os.devnull

else:

else:

DEVNULL = "/dev/null"

DEVNULL = "/dev/null"

(107)

Select

Moduł select służy do nasłuchiwania na wielu Moduł select służy do nasłuchiwania na wielu

gniazdach jednocześnie, co pozwala na gniazdach jednocześnie, co pozwala na

obsługiwanie wielu klientów obsługiwanie wielu klientów

select.select(rlist, wlist, xlist[, timeout]) select.select(rlist, wlist, xlist[, timeout])

http://docs.python.org/library/select.html http://docs.python.org/library/select.html

(108)

Serwer HTTP

from BaseHTTPServer import HTTPServer from BaseHTTPServer import HTTPServer

from SimpleHTTPServer import from SimpleHTTPServer import

SimpleHTTPRequestHandler SimpleHTTPRequestHandler

import os import os

os.chdir(".") os.chdir(".")

serv = HTTPServer(("",8888), serv = HTTPServer(("",8888),

SimpleHTTPRequestHandler) SimpleHTTPRequestHandler)

serv.serve_forever() serv.serve_forever()

(109)

Usługi

python-dnspython – do pracy jako serwer DNS python-dnspython – do pracy jako serwer DNS

httplib – protokół HTTP httplib – protokół HTTP

imaplib – protokół IMAP (poczta) imaplib – protokół IMAP (poczta)

python-zsi – pakiet do tworzenia klienta i serwera python-zsi – pakiet do tworzenia klienta i serwera SOAPSOAP

(110)

Usługi: POP

Do obsługi poczty służy pakiet POP.

Do obsługi poczty służy pakiet POP.

Przykład:

Przykład:

import getpass, poplib import getpass, poplib

#http://docs.python.org/library/poplib.html

#http://docs.python.org/library/poplib.html

#http://docs.python.org/library/getpass.html

#http://docs.python.org/library/getpass.html s = poplib.POP3("poczta.o2.pl")

s = poplib.POP3("poczta.o2.pl") user = raw_input("Login:")

user = raw_input("Login:")

password = getpass.getpass("Haslo:") password = getpass.getpass("Haslo:")

s.user(user) s.user(user)

s.pass_(password) s.pass_(password)

(111)

Usługi: POP

#s.apop(user,password)

#s.apop(user,password) print s.stat()

print s.stat()

print s.stat()[0]

print s.stat()[0]

s.retr(s.stat()[0]) s.retr(s.stat()[0])

top = s.top(s.stat()[0],0) top = s.top(s.stat()[0],0)

print top print top

print filter(lambda item:

print filter(lambda item:

item.startswith('Subject:'), top[1])[0]

item.startswith('Subject:'), top[1])[0]

s.quit() s.quit()

(112)

Usługi: FTP – serwer

#!/usr/bin/env python

#!/usr/bin/env python

from pyftpdlib import ftpserver from pyftpdlib import ftpserver

address = ("0.0.0.0", 21) # listen on every IP on address = ("0.0.0.0", 21) # listen on every IP on

my machine on port 21 my machine on port 21

server = ftpserver.FTPServer(address, server = ftpserver.FTPServer(address,

ftpserver.FTPHandler) ftpserver.FTPHandler) server.serve_forever() server.serve_forever()

(113)

Komunikacja ze stronami

Do pozyskiwania stron służy m.in. urllib.

Do pozyskiwania stron służy m.in. urllib.

urllib.urlopen(url[, data[, proxies]]) – otwiera url urllib.urlopen(url[, data[, proxies]]) – otwiera url

urllib.urlretrieve(url[, filename[, reporthook[, urllib.urlretrieve(url[, filename[, reporthook[,

data]]]) – pobiera url do pliku data]]]) – pobiera url do pliku

http://docs.python.org/library/urllib.html?

http://docs.python.org/library/urllib.html?

highlight=urllib#urllib highlight=urllib#urllib

(114)

Komunikacja ze stronami

Do pozyskiwania stron służy m.in. urllib.

Do pozyskiwania stron służy m.in. urllib.

urllib.urlopen(url[, data[, proxies]]) – otwiera url urllib.urlopen(url[, data[, proxies]]) – otwiera url

urllib.urlretrieve(url[, filename[, reporthook[, urllib.urlretrieve(url[, filename[, reporthook[,

data]]]) – pobiera url do pliku data]]]) – pobiera url do pliku

http://docs.python.org/library/urllib.html?highlight=urllib#urllib http://docs.python.org/library/urllib.html?highlight=urllib#urllib

http://www.boddie.org.uk/python/libxml2dom.html http://www.boddie.org.uk/python/libxml2dom.html

(115)

Parser stron

Libxml2dom służy do parsowania stron.

Libxml2dom służy do parsowania stron.

libxml2dom.parseString(s, html=1) libxml2dom.parseString(s, html=1)

doc.getElementsByTagName("div") doc.getElementsByTagName("div")

first.childNodes first.childNodes

hrefs[0].getAttribute("href") hrefs[0].getAttribute("href")

child_node.TEXT_NODE child_node.TEXT_NODE

child_node.nodeValue child_node.nodeValue

(116)

Twisted

Twisted to silnik do komunikacji sieciowej.

Twisted to silnik do komunikacji sieciowej.

(117)

Twisted - serwery

Klasy serwerowe, które używają Twisted Klasy serwerowe, które używają Twisted

dziedziczą po:

dziedziczą po: twisted.internet.protocol.Protocoltwisted.internet.protocol.Protocol Instancja jest tworzona przy połączeniu i ginie Instancja jest tworzona przy połączeniu i ginie

przy jego zakończeniu.

przy jego zakończeniu.

Konfiguracje persystentne są przechowywane w Konfiguracje persystentne są przechowywane w

klasach dziedziczących po klasie:

klasach dziedziczących po klasie:

twisted.internet.protocol.Factory twisted.internet.protocol.Factory

Metoda

Metoda Factory.buildProtocolFactory.buildProtocol tworzy instancję tworzy instancję Protocol

Protocol dla każdego połączenia. dla każdego połączenia.

Dzięki temu aplikacja może oferować tę samą Dzięki temu aplikacja może oferować tę samą

usługę na wielu portach.

usługę na wielu portach.

(118)

Klasy Protocol

Te klasy asynchronicznie odpowiadają na żądania.

Te klasy asynchronicznie odpowiadają na żądania.

Przykład (serwer echa):

Przykład (serwer echa):

from twisted.internet.protocol import Protocol from twisted.internet.protocol import Protocol

class Echo(Protocol):

class Echo(Protocol):

def dataReceived(self, data):def dataReceived(self, data):

self.transport.write(data)self.transport.write(data)

(119)

Klasy Protocol

Istotne metody:

Istotne metody:

dataRecieved dataRecieved

connectionMade connectionMade

connectionLost connectionLost

Cytaty

Powiązane dokumenty

(4) Ti może założyć zamek X,SIX,IX na węzeł Q tylko wtedy, gdy rodzic(Q) ma zamek IX lub SIX założony przez transakcję Ti. (5) Ti zakłada

• Otwarcie połączenia z bazą danych jest drogie, ale wielokrotne użycie tanie. – Używaj

– Brak promocji zamków w Oracle; Parametry DB2 ustawione, żeby nie było promocji zamków; brak takiej kontroli w SQL Server. – Dual Xeon (550MHz,512Kb), 1Gb

– Zapis do pamięci podręcznej: transfer kończy się, gdy dane znajdą się w pamięci podręcznej sterownika. • Baterie gwarantują zapis przy

• Punkt kontrolny (częściowy zrzut brudnych strona na dysk) odbywa się w stałych odstępach lub po zapełnieniu dziennika:. – Wpływa na wydajność bazy + Pozwala

– Jeśli często odczytuje się adres dostawcy na podstawie numeru zamówionej części, to schemat 1 jest dobry.. – Jeśli jest wiele dodawanych wiele zamówień, schemat 1

• Indeks niepogrupowany jest dobry, gdy używające go zapytania zwracają znacznie mniej rekordów niż jest stron w tabeli. •

• DISTINCT jest zbędny, ponieważ ssnum jest kluczem w employee, więc też i kluczem w podzbiorze relacji employee...