Upload
carver
View
44
Download
0
Embed Size (px)
DESCRIPTION
Komunikacja człowiek - komputer. Wykład 3. Pliki i bazy danych w Pythonie. Literatura: Jakub Swacha – kurs Pythona http://uoo.univ.szczecin.pl/~jakubs/ Marcin Młotkowski – kurs języka Python http://www.ii.uni.wroc.pl/~marcinm/dyd/python/ - PowerPoint PPT Presentation
Citation preview
Komunikacja człowiek - komputer
1
Wykład 3Pliki i bazy danych w Pythonie
Opracował:dr inż. Wojciech [email protected]://wbieniec.kis.p.lodz.plKatedra Informatyki StosowanejPolitechnika Łódzka
Literatura:
Jakub Swacha – kurs Pythonahttp://uoo.univ.szczecin.pl/~jakubs/
Marcin Młotkowski – kurs języka Pythonhttp://www.ii.uni.wroc.pl/~marcinm/dyd/python/
Python 2.6.4 documentationhttp://docs.python.org/
2
Atrybuty:'r' – do odczytu'w' – do zapisu'a' – do ‘appendu’'r+' – do odczytu i zapisu'rb', 'wb', 'ab' – odczyt i zapis binarny
f.close() – zamyka plik
Otwarcie i zamknięcie pliku:f = open('plik', 'r')
Otwieranie plików
Atrybuty obiektu plikowego
3
closed określa czy plik jest zamknięty >>> f1.closedfalse
Obiekty plikowe mają trzy podstawowe atrybuty:
name zawiera nazwę pliku (tak jak podano ją przy otwarciu) >>> f1.name'plik1.txt'mode określa tryb, w jakim otwarto plik >>> f1.mode'w'
Błędy i wyjątki – otwarcie nieistniejącego pliku
4
>>> try:... fsock = open("c:/niemapliku.txt") ... except IOError: ... print "Plik nie istnieje" ... print "Ta linia zawsze zostanie wypisana"Plik nie istnieje Ta linia zawsze zostanie wypisana
>>> f = open("plik", "r")Traceback (most recent call last): File "<stdin>", line 1, in ? IOError: [Errno 2] No such file or directory: 'plik'
Plik nie istnieje i dlatego zostanie rzucony wyjątek IOError. Ponieważ nie przechwytujemy tego wyjątku, Python po prostu wypisuje błąd i zakańcza działanie programu.
Czytanie pliku tekstowego
5
f.readlines() – zwraca listę wierszy
f.read() – odczyt całego pliku
f.read(l_zn) – odczyt tylko l_zn znaków. Zwracany jest string
f.readline() – odczytuje jeden wiersz. Zwracamy razem ze znakiem "\n"
Obsługa błędów czytania
6
try:f = open(filename, "rb", 0)try:
f.seek(-128, 2)tagdata = f.read(128)
finally:f.close()
except IOError:pass
IOError może być rzucony przez:- open (plik może nie istnieć), - seek (plik może być mniejszy niż 128 bajtów)- read (być może dysk posiada uszkodzony sektor)
kod z bloku finally zostanie zawsze wykonany, nawet jeśli jakaś instrukcja bloku try rzuci wyjątek. Pass jest wyrażeniem Pythona, które nic nie robi.
Przykłady czytania pliku
7
f = open('test.py', 'r')while True:
wiersz = f.readline()if len(wiersz) == 0: breakprint wiersz,
f.close()
f = open('test.py', 'r')for wiersz in f:print wiersz,
words = open("c:/730.txt").read().split()print words[:30]print words.count("Oliver")print words.count("Twist")print len(set(words))
8
f = open("Feel.mp3","rb")print f.tell() f.seek(-128, 2)print f.tell() tagData = f.read(128) print tagDataprint f.tell()
read czyta określoną liczbę bajtów z otwartego pliku i zwraca dane w postaci łańcucha znaków, które zostały odczytane. Opcjonalny argument określa maksymalną liczbę bajtów do odczytu. Jeśli nie zostanie podany argument, read będzie czytał do końca pliku.
tell zwraca aktualną pozycję w otwartym pliku.
seek służy do poruszania się po otwartym pliku. Drugi argument: 0 – pozycja bezwzgledna, 1 – względem pozycji aktualnej 2 – względem końca
Przykład: czytanie TAG z MP3
Zapis do pliku
9
Plik musi być otwarty w trybie do zapisu lub odczytu i zapisu 'w', 'a', 'r+'
f.write(string) zapisuje zawartość łańcucha string ale nic nie zwraca
>>> f.write('This is a test\n')
Aby zapisać dane innego typu muszą być skonwertowane na string
value = ('the answer', 42) s = str(value)f.write(s)
f = ('/tmp/workfile', 'r+') f.write('0123456789abcdef')f.seek(5)print f.read(1) #wypisze 5f.seek(-3, 2) #3 bajt przed końcemf.read(1) #wypisze d
10
n=raw_input("Podaj pełną nazwę pliku do skopiowania>") oryg = file(n,"rb") kop = file("kopia "+n,"wb")# otwieramy kopię do zapisuwhile True: b = oryg.read(1) # wczytujemy 1 bajt z oryginału if not b: break # Koniec pliku! kop.write(b) kop.close() oryg.close() print "Kopiowanie zakończone pomyślnie"
Kopiowanie pliku
11
t=raw_input("Podaj pełną nazwę pliku >")p=input("Podaj przesunięcie >”)f1 = open(t,"r+b") s=f1.read() sz="" # sz oznacza tekst zaszyfrowanyfor c in s: a=ord(c) # wyliczamy kod ASCII if a > 32: # znaków białych i sterujących nie szyfrujemy c=chr((a+p) % 256) # inne przesuwamy sz+=c # dodajemy do szf1.seek(0) # ustawiamy pozycję pliku na jego początkuf1.write(sz) # zapisujmy szf1.close() # zamykamy plik
Kodowanie pliku
Zapisywanie całych wierszy
12
lista = ["napis1", "napis 2", "napis 3"]g=open("test.txt","w")g.writelines(lista) #zapisuje do pliku listę, oddziela znakiem " "g.close()
f.writelines(['to\n', 'są\n', 'kolejne\n', 'wiersze\n'])
13
Pliki i struktury: MP3 TAG
Obsługa pliku *.ini
14
Obsługa pliku *.ini
15
import ConfigParserimport sysconfig = ConfigParser.ConfigParser() config.add_section("book") config.set("book", "title", "the python standard library") config.set("book", "author", "fredrik lundh") config.add_section("ematter")config.set("ematter", "pages", 250) config.write(sys.stdout)
[book]title = the python standard libraryauthor = fredrik lundh[ematter]pages = 250
Obsługa pliku *.ini – zmiany
16
Usuwanie:ini.remove_option('window', 'height')ini.remove_section('window')
Modyfikacja parametrów:ini.set('window', 'height', 100)
Zapis konfiguracjif = open('konfig.ini', 'w')ini.write(f)fh.close()
Obsługa plików CSV
17
CSV – Comma Separated Values
Dane"Anna", "Kowalska", 2000-01-01, 3"Jan", "Nowak", 2006-04-01, 2Notowania giełdowe2006-04-26;1415.79;183.29;102.14;2006-04-25;1415.88;183.43;102.31;Parametry formatu:
delimiter – separator, np. ',' ';' ':‘lineterminator – koniec wierszaquotechar – znak cudzysłowuquoting – kiedy ujmować pola w cudzysłów:QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE
Odczyt i zapis pliku CSV
18
import csvreader = csv.reader(open('/etc/passwd', 'r'), delimiter=':', quoting=csv.QUOTE_NONE)for row in reader:print row
import csvdata = [ [1, 'Kubus'], [2, 'Puchatek'] ]writer = csv.writer( open('out', "w"), dialect=csv.excel)writer.writerows(data)
CSV - Wykorzystanie słowników
19
fh = open('notowania.csv', "r")reader = csv.DictReader(fh, delimiter=';')for row in reader: for k in row.keys(): print k, row[k]
fh = open('notowania.csv', "r")klucze = ['lp', 'name']reader = csv.DictReader(fh, fieldnames= klucze)for row in reader: print row['lp'], row['name']
Własne klucze:
20
Rekord Rekord Rekord Rekord Rekord Rekord
Indeks(int) Imię (char[20] Nazwisko (char[30]) Ocena (float) Semestr(byte) Grupa(char[5])
Rekord
Plik
Pliki rekordowe
21
f=open("studenci","wb")
imie="Jan"
nazwisko="Kowalski"
indeks=70678
ocena=4.5
semestr=3
grupa="3D20"
import struct
rekord=struct.pack("<L20s30sfb5s",indeks,imie,nazwisko,ocena,semest
r,grupa)
f.write(rekord)
f.close()
Plik rekordowy – użycie struct
Struct – znaczenie symboli
22
Format Typ języka C Python
x pad byte brak wartości
c char napis o długości 1
b signed char integer
B unsigned char integer
h short integer
H unsigned short integer
i int integerI unsigned int longl long integer
L unsigned long long
q long long long
Q unsigned long long long
f float floatd double floats char[] stringp char[] stringP void * integer
Znaczenie pierwszego znaku
23
Znak Porządek bajtów Rozmiari wyrównanie
@ odpowiedni dla maszyny
odpowiedni dla maszyny
= odpowiedni dla maszyny standardowy
< little-endian standardowy
> big-endian standardowy
! sieciowy (= big-endian) standardowy
Jeśli pierwszym znakiem napisu nie jest żaden z powyższych, przyjmuje się interpretację odpowiadającą znakowi "@". Porządkiem bajtów odpowiednim dla maszyny może być zarówno big-endian jak i little-endian, w zależności od systemu, na którym wykonywany jest program. Przykładowo, procesory firm Motorola oraz Sun używają porządku bajtów big-endian; procesory firm Intel oraz DEC używają little-endian.
Odczyt pliku rekordowego
24
g=open("studenci","rb")
sr=struct.calcsize("<L20s30sfb5s")
while True:
rek = g.read(sr)
if not rek: break
indeks,imie,nazwisko,ocena,semestr,grupa=\
struct.unpack("<L20s30sfb5s",rek)
print indeks,imie,nazwisko,ocena,semestr,grupa
g.close()
25
Serializacja obiektu polega na przekształceniu danych go opisujących w ciąg bajtów (funkcja dumps), z którego można później odtworzyć taki sam obiekt (funkcja loads).
Serializacja obiektów
Serializacja własnych obiektów
26
class wymiary3:
x=0; y=0; z=0
w3=wymiary3()
w3.x=1; w3.y=2; w3.z=3
zapis=pickle.dumps(w3)
del w3
w3=pickle.loads(zapis)
print w3.x; w3.y; w3.z
Dzięki pickle można serializować obiekty należące do klas zdefiniowanych przez nas.
Zapis bezpośrednio do pliku
27
f1=file("trzy_rzeczy.txt","w+")pickle.dump((lista,slownik,w3),f1)lista=[]; slownik={}; w3=wymiary3()print lista; slownik; w3.x
[]{}0
f1.seek(0)(lista,slownik,w3)=pickle.load(f1)print lista; slownik; w3.x
[1, 2, 'trzy', 4]{'a': 'b', 1: 2}1
Moduł dumbdbm
28
Moduł tworzy słownik zapisany na dysku. Składa się on z dwóch plików „.dat” i indeksującego „.dir”). Obsługa bazy jest identyczna jak obsługa słownika, z tą różnicą, że wszystkie zachowane w niej dane przechowywane są nie w pamięci, lecz na dysku.
import dumbdbm
db=dumbdbm.open("prosta_baza")
db['napis']="hej ho!"
print db['napis']
db.close()
Bazy danych typu dbm pozwalają używać napisów jako kluczy i wartości. Próba zachowania w niej obiektu innego niż napis typu, nieuchronnie kończy się błędem
Moduł shelve
29
analogiczny sposób dostępu do danych (podobny słownikowi), umożliwiając jednak zachowywanie obiektów dowolnego typu (nie tylko napisów)
import shelve
lista = [1, 2, "trzy", 4]
slownik={"a":"b",1:2}
db = shelve.open ('baza')
db['lista']=lista
db['slownik']=slownik
Moduł shelve - możliwości
30
liczba elementów:>>> len(db)2
Sprawdzenie istnienia klucza:>>> 'lista' in dbTrue
Lista kluczy:>>> db.keys()['lista', 'slownik']
Moduł shelve - możliwości
31
Wyszukanie wartości po kluczu>>> db['lista'][1, 2, 'trzy', 4]>>> db['slownik']{'a': 'b', 1: 2}
Lista wartości:>>> db.values()[[1, 2, 'trzy', 4], {'a': 'b', 1: 2}]
Lista elementów:>>> db.items()[('lista', [1, 2, 'trzy', 4]), ('slownik', {'a': 'b', 1: 2})]
Moduł shelve - możliwości
32
Modyfikacja wartości:>>> db['lista']=[3,2]
Usunięcie elementu:>>> del db['lista']>>> db.items()[('slownik', {'a': 'b', 1: 2})]
Usunięcie wszystkich elementów:>>> db.clear()>>> db.items()[]
Zamknięcie bazy>>> db.close()
Baza danych SQLite
33
Możliwe jest tworzenie wstępnej wersji aplikacji z wykorzystaniem SQLite, a następnie przeniesienie jej na standardowy serwer bazy danych (PostgreSQL czy Oracle)
SQLite to biblioteka napisana w języku C
Obsługuje "lekką" bazę danych w postaci jednego pliku na dysku.
Nie wymaga instalacji serwera ani łączenia się z serwerem.
Używa odmiany języka SQL
Może być używana jako struktura danych skojarzona z aplikacją
Implementuje DB API 2.0 z rozszerzeniami
Proste operacje na bazie
34
import sqlite3
db = sqlite3.connect('temp.db')
kursor = db.cursor()
kursor.execute("create table Student(nazwisko text, imie text, indeks int,
ocena real)")
db.commit()kursor.execute("insert into Student values('Kowalski' , 'Jan' , 70660, 4.5)")
kursor.execute('SELECT * FROM Student')
for row in kursor:
print row
kursor.close()
Zapytanie sparametryzowane
35
# NIE! – niebezpieczne nazwisko = 'Kowalski' kursor.execute("select * from Student where nazwisko = '%s' " % nazwisko)
Czasem zapytanie będzie wykorzystywać zmienne z programu. Sklejanie zapytania poprzez użycie operacji na stringach w Pythonie może być niebezpieczne (narażenie na atak Injection).W zamian należy użyć symbol zastępczy.
# TAK! t = (nazwisko,) kursor.execute('select * from Student where nazwisko=?', t)
# Bardziej złożony przykładfor t in [('Kowalski', 'Jan', 70123, 4.5), ('Wisniewski', 'Maciej', 143245, 3.5), ('Nowak', 'Grzegorz', 132322, 3), ]: kursor.execute('insert into Studencivalues (?,?,?,?)', t)
SQLite w pamięci i generatory
36
import sqlite3
def char_generator():
import string
for c in string.letters[:26]:
yield (c,)
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table characters(c)")
cur.executemany("insert into characters(c) values (?)", char_generator())
cur.execute("select c from characters")
print cur.fetchall()
„Prawdziwe” bazy danych
37
Python obsługuje różne serwery relacyjnych baz danych między innymi:OracleDB/2MySQLPostgreSQLMS SQL
Python Database API SpecificationZunifikowany interfejs (metody i pola) dostępu do różnych silników relacyjnych baz danych (Aktualna wersja: 2.0)
Korzystanie z MySQL
38
import MySQLdb
db = MySQLdb.connect(host='localhost', db='studenci', user='root',
passwd='root')wynik = db.cursor()
wynik.execute('SELECT * FROM Student')
row = wynik.fetchone()
while row:
print row
row = wynik.fetchone()
wynik.close()
db.close()