Poprzedni wykład     Lista wykładów     Następny wykład

Operacje wejścia/wyjścia

Czytanie z konsoli Pisanie na konsolę Obsługa plików tekstowych Obsługa błędów

Czytanie z konsoli

Istnieją dwie funkcje czytające z konsoli. Najczęściej pytamy użytkownika o liczbę lub tekst.
O tekst zdecydowanie lepiej pytać funkcją raw_input.
s = raw_input("Podaj imię: ")
Podaj imię: Jan
s => 'Jan'
s=input("Podaj imię: ")
Podaj imię: Jan
...
NameError: name 'Jan' is not defined
s = input("Podaj imię: ")
Podaj imię: 'Jan'
s => 'Jan'
Błąd został spowodowany tym, że interpreter próbował wyliczyć wartość wyrażenia Jan, tzn. szukał zmiennej o nazwie Jan i chciał zwrócić jej wartość.
Przy pytaniu o liczbę oba sposoby mają swoje zalety i wady.
n = raw_input("Podaj liczbę całkowitą: ")
Podaj liczbę całkowitą: 22
n**2
...
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
Zmienna n jest typu str i nie można jej potęgować. Należy wykonać konwersję:
int(n)**2 => 484
Również teraz można zobaczyć komunikat o błędzie, przecież konwersja zmiennej n na typ int może być niemożliwa. Można skorzystać z obsługi błędów.
while True:
    try:
        n=int(raw_input("Podaj liczbę całkowitą: "))
        break
    except ValueError:
        print "To nie jest liczba całkowita"
Główną zaletą pytania o liczbę przy pomocy funkcji input jest umożliwienie użytkownikowi wpisania wzoru wyliczającego liczbę.
from math import *
print "Wpisując liczby możesz używać funkcji i operatorów matematycznych"
x = input("Podaj liczbę: ")
Podaj liczbę: sin(37)*exp(11)+(12.56/7.11)**4 
x => -38521.5551629014
Użytkownik ma możliwość popełnienia najromaitszych błędów: błędy składniowe sin(33)), niepoprawne operacje matematyczne (dzielenie przez zero, logarytmowanie liczb ujemnych, ...), błędne nazwy funkcji, użycie nieistniejących zmiennych. Lekarstwem jest obsługa błędów.
while True:
    try:
        x=input("Podaj liczbę: ")
        break
    except Error:
        pass

Spis treści

Pisanie na konsolę

Najprostszy sposób wypisania wartości zmiennej x, to wpisanie polecenia: x. Ten sposób działa tylko w trybie interaktywnym, nie działa w programach.
Wypisując w ten sposób nie możemy formatować wyjścia. Uniwersalny sposób wypisywania, to polecenie print lista_obiektów_rozdzielonych_przecinkami. Wypisywane są wszystkie obiekty odzielone spacjami, w razie konieczności obiekty są konwertowane do typu str.
print 33, 'druk' => 33 druk
Za ostatnim obiektem wypisywany jest znak przejścia do nowego wiersza "\n", można temu zapobiec pisząc przecinek po liście obiektów (również po ostatnim obiekcie zostanie wówczas wypisana spacja). Różnicę można zobaczyć tylko podczas wykonywania programów.
Zawartość pliku pr.py:
print 33,
print 44
print 33
print 44
Po poleceniach python pr.py lub import pr w konsoli Pythona pojawią się napisy:
33 44
33
44
Do formatowanego pisania na konsoli służy polecenie: print napis_zawierający_sekwencje_formatujące % krotka_obiektów. Krotki, to jeden z typów złozonych. Omówione zostały tutaj. Przykład (z jednoelementową krotką):
x = 22.33
print "x = %i" % x => x = 22
Sekwencji formatujących musi być tyle samo ile jest elementów w krotce. Sekwencja formatująca ma postać %[opcja][rozmiar]format. Rozmiar i opcja są nieobowiązkowe. Formaty: Opcje
print "%10s%10s%10s" % ("n","n*n","n*n*n")
for i in range(1,21):
    print "%10i%10i%10i" % (i,i**2,i**3)
=>
         n       n*n     n*n*n
         1         1         1
         2         4         8
        ..        ..      ....
        20        40      8000

Spis treści

Obsługa plików tekstowych

Plik, z którego chcemy korzystać (czytanie lub pisanie) musimy wpierw otworzyć. A po użyciu musimy go zamknąć. W każdym otwartym pliku jest wskaźnik (liczba) wskazująca aktualną pozycję (jest to ilość bajtów od początku pliku). Po otwarciu wskaźnik ten ma wartość 0. Do wędrowania po pliku służy dwuargumentowa metoda seek(): Metody czytające respektują położenie wskaźnika. Metody piszące nie zwracają uwagi na położenie wskaźnika. Zaczynają pisać od początku lub od końca pliku, decyduje mode - drugi parametr funkcji open. Trzy proste sposoby wypisywania zawartości pliku tekstowego. Pominięta została obsługa błędów, np. brak pliku. Plik jest otwierany raz, ale czytany trzy razy, przed drugim i trzecim czytaniem konieczne jest zatem przesunięcie wskaźnika na początek pliku.
f = open("test.txt")
while True:
    s = f.readline()
    if len(s) == 0:
        break
    print s,

f.seek(0)
l = f.readlines()
for s in l:
    print s,

f.seek(0)
for s in f:
    print s,

f.close()

Python zawiera moduły do pracy z plikami tekstowymi o bardziej regularnej budowie. Do wymiany danych między programami sa często używane pliki csv. Mają one postać tabelki [z nagłówkiem]. Z systemu USOS można pobrać plik z listą studentów mający taką budowę:

"imie";"nazwisko";"indeks";"pesel";"skreslony"
"Jakub";"Tomaszewski";"111111";"33333333333";"0"
"Piotr";"Sapieha";"222222";"22222222222";"0"
Nie istnieje standard formatu plików csv, ważne parametry, to: Przykładowy program odczytujący plik z lista studentów i wyświetlający w kolumnach imiona, nazwiska i numery indeksów:
import csv
f = open("g11.csv")
reader = csf.reader(f,delimiter=";",quoting=csv.QUOTE_ALL)
reader.next() #przejście do następnego (czyli drugiego) wiersza, w pierwszym nie ma danych
for w in reader:
    print "%12s%20s%8s" % w[0],w[1],w[2]
f.close()
Każdy odczytany wiersz ma postać listy, przy tworzeniu pliku csv dane do zapisania w wierszu też powinny byc listą, w poniższym przykładzie całość danych jest listą list.
import csv
f = open("test.csv","w")
writer = csv.writer(f,delimiter=";",quoting=csv.QUOTE_NONNUMERIC,lineterminator="\n")
dane = [[1,"jeden"],[2,"dwa"],[3,"trzy"]]
writer.writerows(dane)
f.close()
utworzony zostanie plik z taką zawartością:
1;"jeden"
2;"dwa"
3;"trzy"

Spis treści

Obsługa błędów

Główne zastosowania obsługi błędów, to kulturalna obsługa niepowodzeń programu nie wynikających z błędów programisty. Kulturalna, tzn. bez komunikatów typu:
 
Traceback (most recent call last):
.....
Typowe zastosowania: Przykład, chcemy pobrac od użytkownika nazwę pliku tekstowego, a następnie znaleźć w podanym pliku wiersz mający postać liczby całkowitej i odczytać tę liczbę.
x = False
while True: #pętla nieskończona
    try:
        s = raw_input("Nazwa pliku: ")
        f = open(s,'r')
        break #przerwanie pętli bo udało się otworzyć plik
    except IOError:
        print "Plik "+s+" nie istnieje lub jest niedostępny"
for linia in f:
    try:
        x = int(linia) #konwersja na typ całkowity
        break
    except ValueError:
        pass
f.close()      
print x => 145 # lub False jeżeli żaden wiersz nie ma postaci liczby
Często jest tak, że wykonanie fragmentu kodu może spowodować błędy różnych typów, i chcemy różne błędy odmiennie obsługiwać.
f = None
try:
    f = open('liczby.txt')
    x = float(f.readline())
    a = 2/x
except IOError:
    print 'Nie mogę odczytać pliku liczby.txt'
except ValueError:
    print 'Pierwszy wiersz pliku liczba.txt nie jest liczbą'
except ZeroDivisionError:
    print 'Pierwszy wiersz pliku liczba.txt zawiera liczbę 0'
except:
    print 'Nierozpoznany błąd'
finally:
    print 'Kończę'
    if not f == None: 
       f.close()
Ostatnia klauzula except może nie zawierać typu błędu. Kod zawarty w klauzuli finally wykona się zawsze - niezależnie od tego czy wystąpił błąd, czy nie. Ten kod służy do "posprzątania", tzn. pozamykania otwartych plików, pozamykania połączeń z bazą danych, z internetem itp.

Przed klauzulą finally, a po wszystkich klauzulach except możemy umieścić klauzulę else. Zawarty w niej kod wykona się gdy w sekcji try nie zostanie żaden wygenerowany wyjątek:

def divide(x,y):
    try:
       wynik = x/y
    except ZeroDivisionError:
       print 'Dzielenie przez zero'
    else:
       print 'Wynik dzielenia =',wynik
    finally:
       print 'Sekcja finally' 
divide(2,1) =>
Wynik dzielenia = 2
Sekcja finally
divide(2,0) =>
Dzielenie przez zero
Sekcja finally

Spis treści
Poprzedni wykład     Lista wykładów     Następny wykład