Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00657 007492 13270097 na godz. na dobę w sumie
Python. Receptury. Wydanie III - książka
Python. Receptury. Wydanie III - książka
Autor: , Liczba stron: 600
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-8180-8 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> python - programowanie
Porównaj ceny (książka, ebook, audiobook).

Python to język programowania z ponad 20-letnią historią. Opracowany na początku lat 90. ubiegłego wieku, błyskawicznie zdobył sympatię programistów. Jest używany zarówno do pisania przydatnych skryptów czy małych narzędzi, jak i do pracy nad dużymi projektami. Korzysta z automatycznego zarządzania pamięcią oraz pozwala na podejście obiektowe i funkcyjne do tworzonego programu. Wokół języka Python skupiona jest bardzo silna społeczność programistów.

Ta książka to sprawdzone źródło informacji na temat Pythona i jego najczęstszych zastosowań. Należy ona do cenionej serii „Receptury”, w której znajdziesz najlepsze sposoby rozwiązywania problemów. Przekonaj się, jak wydajnie operować na strukturach danych, łańcuchach znaków, tekście i liczbach. Zobacz, jak korzystać z iteratorów i generatorów. Ponadto naucz się tworzyć własne klasy i funkcje oraz sprawdź, jak uzyskać dostęp do plików i sieci. Te i dziesiątki innych receptur opisano w tej książce. To obowiązkowa pozycja na półce każdego programisty pracującego z językiem Python.

Dzięki tej książce:

Najlepsze rozwiązania typowych problemów!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: Python Cookbook, 3rd Edition Tłumaczenie: Tomasz Walczak ISBN: 978-83-246-8180-8 © 2014 Helion S.A. Authorized Polish translation of the English edition of Python Cookbook, 3rd Edition, ISBN 9781449340377 © 2013 David Beazley, Brian Jones. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/pytre3 Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/pytre3.zip Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:316)ci Przedmowa ...................................................................................................................11 1. Algorytmy i struktury danych ..................................................................................... 15 15 16 19 20 22 24 25 26 28 29 30 31 33 34 35 37 39 40 42 43 1.1. Wypakowywanie sekwencji do odr(cid:246)bnych zmiennych 1.2. Wypakowywanie elementów z obiektów iterowalnych o dowolnej d(cid:228)ugo(cid:264)ci 1.3. Zachowywanie ostatnich N elementów 1.4. Wyszukiwanie N najwi(cid:246)kszych lub najmniejszych elementów 1.5. Tworzenie kolejki priorytetowej 1.6. Odwzorowywanie kluczy na ró(cid:276)ne warto(cid:264)ci ze s(cid:228)ownika 1.7. Okre(cid:264)lanie uporz(cid:241)dkowania w s(cid:228)ownikach 1.8. Obliczenia na danych ze s(cid:228)owników 1.9. Wyszukiwanie identycznych danych w dwóch s(cid:228)ownikach 1.10. Usuwanie powtórze(cid:254) z sekwencji przy zachowaniu kolejno(cid:264)ci elementów 1.11. Nazywanie wycinków 1.12. Okre(cid:264)lanie najcz(cid:246)(cid:264)ciej wyst(cid:246)puj(cid:241)cych w sekwencji elementów 1.13. Sortowanie list s(cid:228)owników wed(cid:228)ug wspólnych kluczy 1.14. Sortowanie obiektów bez wbudowanej obs(cid:228)ugi porówna(cid:254) 1.15. Grupowanie rekordów na podstawie warto(cid:264)ci pola 1.16. Filtrowanie elementów sekwencji 1.17. Pobieranie podzbioru s(cid:228)ownika 1.18. Odwzorowywanie nazw na elementy sekwencji 1.19. Jednoczesne przekszta(cid:228)canie i redukowanie danych 1.20. (cid:227)(cid:241)czenie wielu odwzorowa(cid:254) w jedno 2. (cid:292)a(cid:295)cuchy znaków i tekst .............................................................................................47 2.1. Podzia(cid:228) (cid:228)a(cid:254)cuchów znaków po wykryciu dowolnego z ró(cid:276)nych ograniczników 47 2.2. Dopasowywanie tekstu do pocz(cid:241)tkowej lub ko(cid:254)cowej cz(cid:246)(cid:264)ci (cid:228)a(cid:254)cucha znaków 48 2.3. Dopasowywanie (cid:228)a(cid:254)cuchów znaków za pomoc(cid:241) symboli wieloznacznych pow(cid:228)oki 50 2.4. Dopasowywanie i wyszukiwanie wzorców tekstowych 51 3 Kup książkęPoleć książkę 54 2.5. Wyszukiwanie i zast(cid:246)powanie tekstu 55 2.6. Wyszukiwanie i zast(cid:246)powanie tekstu bez uwzgl(cid:246)dniania wielko(cid:264)ci liter 2.7. Tworzenie wyra(cid:276)e(cid:254) regularnych w celu uzyskania najkrótszego dopasowania 56 2.8. Tworzenie wyra(cid:276)e(cid:254) regularnych dopasowywanych do wielowierszowych wzorców 57 2.9. Przekszta(cid:228)canie tekstu w formacie Unicode na posta(cid:232) standardow(cid:241) 58 60 2.10. U(cid:276)ywanie znaków Unicode w wyra(cid:276)eniach regularnych 61 2.11. Usuwanie niepo(cid:276)(cid:241)danych znaków z (cid:228)a(cid:254)cuchów 62 2.12. Zapewnianie poprawno(cid:264)ci i porz(cid:241)dkowanie tekstu 2.13. Wyrównywanie (cid:228)a(cid:254)cuchów znaków 64 66 2.14. (cid:227)(cid:241)czenie (cid:228)a(cid:254)cuchów znaków 68 2.15. Podstawianie warto(cid:264)ci za zmienne w (cid:228)a(cid:254)cuchach znaków 70 2.16. Formatowanie tekstu w celu uzyskania okre(cid:264)lonej liczby kolumn 2.17. Obs(cid:228)ugiwanie encji HTML-a i XML-a w tek(cid:264)cie 71 73 2.18. Podzia(cid:228) tekstu na tokeny 75 2.19. Tworzenie prostego rekurencyjnego parsera zst(cid:246)puj(cid:241)cego 2.20. Przeprowadzanie operacji tekstowych na (cid:228)a(cid:254)cuchach bajtów 83 3. Liczby, daty i czas ........................................................................................................87 87 3.1. Zaokr(cid:241)glanie liczb 88 3.2. Przeprowadzanie dok(cid:228)adnych oblicze(cid:254) na liczbach dziesi(cid:246)tnych 90 3.3. Formatowanie liczb w celu ich wy(cid:264)wietlenia 92 3.4. Stosowanie dwójkowych, ósemkowych i szesnastkowych liczb ca(cid:228)kowitych 93 3.5. Pakowanie do bajtów i wypakowywanie z bajtów du(cid:276)ych liczb ca(cid:228)kowitych 95 3.6. Przeprowadzanie oblicze(cid:254) na liczbach zespolonych 96 3.7. Niesko(cid:254)czono(cid:264)(cid:232) i warto(cid:264)ci NaN 98 3.8. Obliczenia z wykorzystaniem u(cid:228)amków 99 3.9. Obliczenia z wykorzystaniem du(cid:276)ych tablic liczbowych 102 3.10. Przeprowadzanie operacji na macierzach i z zakresu algebry liniowej 3.11. Losowe pobieranie elementów 103 3.12. Przekszta(cid:228)canie dni na sekundy i inne podstawowe konwersje zwi(cid:241)zane z czasem 105 3.13. Okre(cid:264)lanie daty ostatniego pi(cid:241)tku 107 108 3.14. Okre(cid:264)lanie przedzia(cid:228)u dat odpowiadaj(cid:241)cego bie(cid:276)(cid:241)cemu miesi(cid:241)cowi 110 3.15. Przekszta(cid:228)canie (cid:228)a(cid:254)cuchów znaków na obiekty typu datetime 3.16. Manipulowanie datami z uwzgl(cid:246)dnieniem stref czasowych 111 4. Iteratory i generatory .................................................................................................113 113 4.1. R(cid:246)czne korzystanie z iteratora 114 4.2. Delegowanie procesu iterowania 4.3. Tworzenie nowych wzorców iterowania z wykorzystaniem generatorów 115 117 4.4. Implementowanie protoko(cid:228)u iteratora 4.5. Iterowanie w odwrotnej kolejno(cid:264)ci 119 4 (cid:95) Spis tre(cid:316)ci Kup książkęPoleć książkę 4.6. Definiowanie funkcji generatorów z dodatkowym stanem 4.7. Pobieranie wycinków danych zwracanych przez iterator 4.8. Pomijanie pierwszej cz(cid:246)(cid:264)ci obiektu iterowalnego 4.9. Iterowanie po wszystkich mo(cid:276)liwych kombinacjach lub permutacjach 4.10. Przechodzenie po parach indeks – warto(cid:264)(cid:232) sekwencji 4.11. Jednoczesne przechodzenie po wielu sekwencjach 4.12. Przechodzenie po elementach z odr(cid:246)bnych kontenerów 4.13. Tworzenie potoków przetwarzania danych 4.14. Przekszta(cid:228)canie zagnie(cid:276)d(cid:276)onych sekwencji na posta(cid:232) jednowymiarow(cid:241) 4.15. Przechodzenie po scalonych posortowanych obiektach iterowalnych zgodnie z kolejno(cid:264)ci(cid:241) sortowania 4.16. Zast(cid:246)powanie niesko(cid:254)czonych p(cid:246)tli while iteratorem 120 121 122 124 125 127 129 130 133 134 135 5. Pliki i operacje wej(cid:316)cia-wyj(cid:316)cia .................................................................................137 137 5.1. Odczyt i zapis danych tekstowych 5.2. Zapisywanie danych z funkcji print() do pliku 139 5.3. Stosowanie niestandardowych separatorów lub ko(cid:254)ca wiersza w funkcji print() 140 141 5.4. Odczyt i zapis danych binarnych 142 5.5. Zapis danych do pliku, który nie istnieje 5.6. Wykonywanie operacji wej(cid:264)cia-wyj(cid:264)cia na (cid:228)a(cid:254)cuchach 143 144 5.7. Odczytywanie i zapisywanie skompresowanych plików z danymi 145 5.8. Przechodzenie po rekordach o sta(cid:228)ej wielko(cid:264)ci 146 5.9. Wczytywanie danych binarnych do zmiennego bufora 5.10. Odwzorowywanie plików binarnych w pami(cid:246)ci 148 150 5.11. Manipulowanie (cid:264)cie(cid:276)kami 151 5.12. Sprawdzanie, czy plik istnieje 152 5.13. Pobieranie listy zawarto(cid:264)ci katalogu 5.14. Nieuwzgl(cid:246)dnianie kodowania nazw plików 153 154 5.15. Wy(cid:264)wietlanie nieprawid(cid:228)owych nazw plików 156 5.16. Dodawanie lub zmienianie kodowania otwartego pliku 5.17. Zapisywanie bajtów w pliku tekstowym 158 159 5.18. Umieszczanie deskryptora istniej(cid:241)cego pliku w obiekcie pliku 160 5.19. Tworzenie tymczasowych plików i katalogów 162 5.20. Komunikowanie z portami szeregowymi 5.21. Serializowanie obiektów Pythona 163 6. Kodowanie i przetwarzanie danych ......................................................................... 167 167 170 174 176 6.1. Wczytywanie i zapisywanie danych CSV 6.2. Wczytywanie i zapisywanie danych w formacie JSON 6.3. Parsowanie prostych danych w XML-u 6.4. Stopniowe parsowanie bardzo du(cid:276)ych plików XML Spis tre(cid:316)ci (cid:95) 5 Kup książkęPoleć książkę 6.5. Przekszta(cid:228)canie s(cid:228)owników na format XML 6.6. Parsowanie, modyfikowanie i ponowne zapisywanie dokumentów XML 6.7. Parsowanie dokumentów XML z przestrzeniami nazw 6.8. Komunikowanie si(cid:246) z relacyjnymi bazami danych 6.9. Dekodowanie i kodowanie cyfr w systemie szesnastkowym 6.10. Dekodowanie i kodowanie warto(cid:264)ci w formacie Base64 6.11. Odczyt i zapis tablic binarnych zawieraj(cid:241)cych struktury 6.12. Wczytywanie zagnie(cid:276)d(cid:276)onych struktur binarnych o zmiennej d(cid:228)ugo(cid:264)ci 6.13. Podsumowywanie danych i obliczanie statystyk 179 181 183 185 187 188 188 192 200 7. Funkcje .......................................................................................................................203 203 7.1. Pisanie funkcji przyjmuj(cid:241)cych dowoln(cid:241) liczb(cid:246) argumentów 7.2. Tworzenie funkcji przyjmuj(cid:241)cych argumenty podawane wy(cid:228)(cid:241)cznie za pomoc(cid:241) s(cid:228)ów kluczowych 7.3. Do(cid:228)(cid:241)czanie metadanych z informacjami do argumentów funkcji 7.4. Zwracanie wielu warto(cid:264)ci przez funkcje 7.5. Definiowanie funkcji z argumentami domy(cid:264)lnymi 7.6. Definiowanie funkcji anonimowych (wewn(cid:241)trzwierszowych) 7.7. Pobieranie warto(cid:264)ci zmiennych w funkcjach anonimowych 7.8. Uruchamianie n-argumentowej jednostki wywo(cid:228)ywalnej z mniejsz(cid:241) liczb(cid:241) argumentów 7.9. Zast(cid:246)powanie klas z jedn(cid:241) metod(cid:241) funkcjami 7.10. Dodatkowy stan w funkcjach wywo(cid:228)ywanych zwrotnie 7.11. Wewn(cid:241)trzwierszowe zapisywanie wywo(cid:228)ywanych zwrotnie funkcji 7.12. Dost(cid:246)p do zmiennych zdefiniowanych w domkni(cid:246)ciu 204 205 206 207 210 211 212 215 216 219 221 8. Klasy i obiekty ............................................................................................................225 225 226 228 230 231 232 236 240 243 246 248 251 254 8.1. Modyfikowanie tekstowej reprezentacji obiektów 8.2. Modyfikowanie formatowania (cid:228)a(cid:254)cuchów znaków 8.3. Dodawanie do obiektów obs(cid:228)ugi protoko(cid:228)u zarz(cid:241)dzania kontekstem 8.4. Zmniejszanie zu(cid:276)ycia pami(cid:246)ci przy tworzeniu du(cid:276)ej liczby obiektów 8.5. Hermetyzowanie nazw w klasie 8.6. Tworzenie atrybutów zarz(cid:241)dzanych 8.7. Wywo(cid:228)ywanie metod klasy bazowej 8.8. Rozszerzanie w(cid:228)a(cid:264)ciwo(cid:264)ci w klasie pochodnej 8.9. Tworzenie nowego rodzaju atrybutów klasy lub egzemplarza 8.10. Stosowanie w(cid:228)a(cid:264)ciwo(cid:264)ci obliczanych w leniwy sposób 8.11. Upraszczanie procesu inicjowania struktur danych 8.12. Definiowanie interfejsu lub abstrakcyjnej klasy bazowej 8.13. Tworzenie modelu danych lub systemu typów 6 (cid:95) Spis tre(cid:316)ci Kup książkęPoleć książkę 8.14. Tworzenie niestandardowych kontenerów 8.15. Delegowanie obs(cid:228)ugi dost(cid:246)pu do atrybutów 8.16. Definiowanie wi(cid:246)cej ni(cid:276) jednego konstruktora w klasie 8.17. Tworzenie obiektów bez wywo(cid:228)ywania metody __init__() 8.18. Rozszerzanie klas za pomoc(cid:241) klas mieszanych 8.19. Implementowanie obiektów ze stanem lub maszyn stanowych 8.20. Wywo(cid:228)ywanie metod obiektu na podstawie nazwy w (cid:228)a(cid:254)cuchu znaków 8.21. Implementowanie wzorca odwiedzaj(cid:241)cy 8.22. Implementowanie wzorca odwiedzaj(cid:241)cy bez stosowania rekurencji 8.23. Zarz(cid:241)dzanie pami(cid:246)ci(cid:241) w cyklicznych strukturach danych 8.24. Tworzenie klas z obs(cid:228)ug(cid:241) porówna(cid:254) 8.25. Tworzenie obiektów zapisywanych w pami(cid:246)ci podr(cid:246)cznej 259 262 266 267 269 273 278 279 283 288 291 293 9. Metaprogramowanie ................................................................................................297 297 9.1. Tworzenie nak(cid:228)adek na funkcje 299 9.2. Zachowywanie metadanych funkcji przy pisaniu dekoratorów 300 9.3. Pobieranie pierwotnej funkcji z nak(cid:228)adki 9.4. Tworzenie dekoratorów przyjmuj(cid:241)cych argumenty 302 9.5. Definiowanie dekoratora z atrybutami dostosowywanymi przez u(cid:276)ytkownika 303 9.6. Definiowanie dekoratorów przyjmuj(cid:241)cych opcjonalny argument 306 307 9.7. Wymuszanie sprawdzania typów w funkcji za pomoc(cid:241) dekoratora 311 9.8. Definiowanie dekoratorów jako elementów klasy 312 9.9. Definiowanie dekoratorów jako klas 9.10. Stosowanie dekoratorów do metod klasy i metod statycznych 315 316 9.11. Pisanie dekoratorów, które dodaj(cid:241) argumenty do funkcji w nak(cid:228)adkach 319 9.12. Stosowanie dekoratorów do poprawiania definicji klas 9.13. U(cid:276)ywanie metaklasy do kontrolowania tworzenia obiektów 320 323 9.14. Sprawdzanie kolejno(cid:264)ci definiowania atrybutów klasy 325 9.15. Definiowanie metaklas przyjmuj(cid:241)cych argumenty opcjonalne 327 9.16. Sprawdzanie sygnatury na podstawie argumentów *args i **kwargs 9.17. Wymuszanie przestrzegania konwencji pisania kodu w klasie 330 332 9.18. Programowe definiowanie klas 335 9.19. Inicjowanie sk(cid:228)adowych klasy w miejscu definicji klasy 337 9.20. Przeci(cid:241)(cid:276)anie metod z wykorzystaniem uwag do funkcji 9.21. Unikanie powtarzaj(cid:241)cych si(cid:246) metod w(cid:228)a(cid:264)ciwo(cid:264)ci 342 344 9.22. Definiowanie w (cid:228)atwy sposób mened(cid:276)erów kontekstu 346 9.23. Wykonywanie kodu powoduj(cid:241)cego lokalne efekty uboczne 9.24. Parsowanie i analizowanie kodu (cid:274)ród(cid:228)owego Pythona 348 351 9.25. Dezasemblacja kodu bajtowego Pythona Spis tre(cid:316)ci (cid:95) 7 Kup książkęPoleć książkę 10. Modu(cid:293)y i pakiety ........................................................................................................355 355 356 357 358 10.1. Tworzenie hierarchicznych pakietów z modu(cid:228)ami 10.2. Kontrolowanie importowania wszystkich symboli 10.3. Importowanie modu(cid:228)ów podrz(cid:246)dnych z pakietu za pomoc(cid:241) nazw wzgl(cid:246)dnych 10.4. Podzia(cid:228) modu(cid:228)u na kilka plików 10.5. Tworzenie odr(cid:246)bnych katalogów z importowanym kodem z jednej przestrzeni nazw 10.6. Ponowne wczytywanie modu(cid:228)ów 10.7. Umo(cid:276)liwianie wykonywania kodu z katalogu lub pliku zip jako g(cid:228)ównego skryptu 10.8. Wczytywanie pliku z danymi z pakietu 10.9. Dodawanie katalogów do zmiennej sys.path 10.10. Importowanie modu(cid:228)ów na podstawie nazwy z (cid:228)a(cid:254)cucha znaków 10.11. Wczytywanie modu(cid:228)ów ze zdalnego komputera z wykorzystaniem haków w poleceniu importu 10.12. Modyfikowanie modu(cid:228)ów w trakcie importowania 10.13. Instalowanie pakietów tylko na w(cid:228)asny u(cid:276)ytek 10.14. Tworzenie nowego (cid:264)rodowiska Pythona 10.15. Rozpowszechnianie pakietów 361 362 364 365 366 367 368 382 384 385 386 11. Sieci i rozwijanie aplikacji sieciowych ......................................................................389 389 11.1. Interakcja z us(cid:228)ugami HTTP za pomoc(cid:241) kodu klienta 393 11.2. Tworzenie serwera TCP 395 11.3. Tworzenie serwera UDP 397 11.4. Generowanie przedzia(cid:228)ów adresów IP na podstawie adresu CIDR 11.5. Tworzenie prostego interfejsu opartego na architekturze REST 399 11.6. Obs(cid:228)uga prostych zdalnych wywo(cid:228)a(cid:254) procedur za pomoc(cid:241) protoko(cid:228)u XML-RPC 403 11.7. Prosta komunikacja mi(cid:246)dzy interpreterami 405 407 11.8. Implementowanie zdalnych wywo(cid:228)a(cid:254) procedur 410 11.9. Proste uwierzytelnianie klientów 11.10. Dodawanie obs(cid:228)ugi protoko(cid:228)u SSL do us(cid:228)ug sieciowych 412 417 11.11. Przekazywanie deskryptora pliku gniazda mi(cid:246)dzy procesami 422 11.12. Operacje wej(cid:264)cia-wyj(cid:264)cia sterowane zdarzeniami 11.13. Wysy(cid:228)anie i odbieranie du(cid:276)ych tablic 427 12. Wspó(cid:293)bie(cid:348)no(cid:316)(cid:235) ...........................................................................................................429 429 432 434 439 441 445 12.1. Uruchamianie i zatrzymywanie w(cid:241)tków 12.2. Ustalanie, czy w(cid:241)tek rozpocz(cid:241)(cid:228) prac(cid:246) 12.3. Komunikowanie si(cid:246) mi(cid:246)dzy w(cid:241)tkami 12.4. Blokowanie sekcji krytycznej 12.5. Blokowanie z unikaniem zakleszczenia 12.6. Zapisywanie stanu w(cid:241)tku 8 (cid:95) Spis tre(cid:316)ci Kup książkęPoleć książkę 12.7. Tworzenie puli w(cid:241)tków 12.8. Proste programowanie równoleg(cid:228)e 12.9. Jak radzi(cid:232) sobie z mechanizmem GIL (i przesta(cid:232) si(cid:246) nim martwi(cid:232)) 12.10. Definiowanie zada(cid:254) dzia(cid:228)aj(cid:241)cych jak aktory 12.11. Przesy(cid:228)anie komunikatów w modelu publikuj-subskrybuj 12.12. U(cid:276)ywanie generatorów zamiast w(cid:241)tków 12.13. Odpytywanie wielu kolejek w(cid:241)tków 12.14. Uruchamianie procesu demona w systemie Unix 446 449 453 456 459 462 468 471 13. Skrypty narz(cid:253)dziowe i zarz(cid:233)dzanie systemem ........................................................475 13.1. Przyjmowanie danych wej(cid:264)ciowych skryptu za pomoc(cid:241) przekierowa(cid:254), potoków lub plików wej(cid:264)ciowych 13.2. Ko(cid:254)czenie pracy programu wy(cid:264)wietleniem komunikatu o b(cid:228)(cid:246)dzie 13.3. Parsowanie opcji z wiersza polece(cid:254) 13.4. Pro(cid:264)ba o podanie has(cid:228)a w czasie wykonywania programu 13.5. Pobieranie rozmiarów terminala 13.6. Wywo(cid:228)ywanie zewn(cid:246)trznych polece(cid:254) i pobieranie danych wyj(cid:264)ciowych 13.7. Kopiowanie lub przenoszenie plików i katalogów 13.8. Tworzenie i wypakowywanie archiwów 13.9. Wyszukiwanie plików na podstawie nazwy 13.10. Wczytywanie plików konfiguracyjnych 13.11. Dodawanie mechanizmu rejestrowania operacji do prostych skryptów 13.12. Dodawanie obs(cid:228)ugi rejestrowania do bibliotek 13.13. Tworzenie stopera 13.14. Okre(cid:264)lanie limitów wykorzystania pami(cid:246)ci i procesora 13.15. Uruchamianie przegl(cid:241)darki internetowej 475 476 477 479 480 481 482 484 485 486 489 491 493 494 495 14. Testowanie, debugowanie i wyj(cid:233)tki ........................................................................497 497 498 501 503 504 505 507 508 510 512 513 514 516 518 14.1. Testowanie danych wyj(cid:264)ciowych wysy(cid:228)anych do strumienia stdout 14.2. Podstawianie obiektów w testach jednostkowych 14.3. Sprawdzanie wyst(cid:241)pienia wyj(cid:241)tków w testach jednostkowych 14.4. Zapisywanie danych wyj(cid:264)ciowych testu w pliku 14.5. Pomijanie testów lub przewidywanie ich niepowodzenia 14.6. Obs(cid:228)uga wielu wyj(cid:241)tków 14.7. Przechwytywanie wszystkich wyj(cid:241)tków 14.8. Tworzenie niestandardowych wyj(cid:241)tków 14.9. Zg(cid:228)aszanie wyj(cid:241)tku w odpowiedzi na wyst(cid:241)pienie innego wyj(cid:241)tku 14.10. Ponowne zg(cid:228)aszanie ostatniego wyj(cid:241)tku 14.11. Wy(cid:264)wietlanie komunikatów ostrzegawczych 14.12. Debugowanie prostych awarii programu 14.13. Profilowanie i pomiar czasu pracy programów 14.14. Przyspieszanie dzia(cid:228)ania programów Spis tre(cid:316)ci (cid:95) 9 Kup książkęPoleć książkę 15. Rozszerzenia w j(cid:253)zyku C ...........................................................................................525 526 15.1. Dost(cid:246)p do kodu w j(cid:246)zyku C za pomoc(cid:241) modu(cid:228)u ctypes 532 15.2. Pisanie prostych modu(cid:228)ów rozszerze(cid:254) w j(cid:246)zyku C 15.3. Pisanie funkcji rozszerze(cid:254) manipuluj(cid:241)cych tablicami 535 15.4. Zarz(cid:241)dzanie nieprzejrzystymi wska(cid:274)nikami w modu(cid:228)ach rozszerze(cid:254) w j(cid:246)zyku C 538 15.5. Definiowanie i eksportowanie interfejsów API j(cid:246)zyka C w modu(cid:228)ach rozszerze(cid:254) 540 544 15.6. Wywo(cid:228)ywanie kodu Pythona w kodzie w j(cid:246)zyku C 548 15.7. Zwalnianie blokady GIL w rozszerzeniach w j(cid:246)zyku C 15.8. Jednoczesne wykonywanie w(cid:241)tków z kodu w j(cid:246)zykach C i Python 549 550 15.9. Umieszczanie kodu w j(cid:246)zyku C w nak(cid:228)adkach opartych na narz(cid:246)dziu Swig 555 15.10. U(cid:276)ywanie Cythona do tworzenia nak(cid:228)adek na istniej(cid:241)cy kod w j(cid:246)zyku C 560 15.11. U(cid:276)ywanie Cythona do pisania wydajnych operacji na tablicach 15.12. Przekszta(cid:228)canie wska(cid:274)nika do funkcji w jednostk(cid:246) wywo(cid:228)ywaln(cid:241) 564 15.13. Przekazywanie (cid:228)a(cid:254)cuchów znaków zako(cid:254)czonych symbolem NULL do bibliotek j(cid:246)zyka C 565 569 15.14. Przekazywanie (cid:228)a(cid:254)cuchów znaków Unicode do bibliotek j(cid:246)zyka C 15.15. Przekszta(cid:228)canie (cid:228)a(cid:254)cuchów znaków z j(cid:246)zyka C na ich odpowiedniki z Pythona 573 15.16. U(cid:276)ywanie (cid:228)a(cid:254)cuchów znaków o nieznanym kodowaniu pobieranych z j(cid:246)zyka C 574 577 15.17. Przekazywanie nazw plików do rozszerze(cid:254) w j(cid:246)zyku C 15.18. Przekazywanie otwartych plików do rozszerze(cid:254) w j(cid:246)zyku C 578 579 15.19. Wczytywanie w j(cid:246)zyku C danych z obiektów podobnych do plików 581 15.20. Pobieranie obiektów iterowalnych w j(cid:246)zyku C 15.21. Diagnozowanie b(cid:228)(cid:246)dów segmentacji 582 A Dalsza lektura ............................................................................................................585 Skorowidz ..................................................................................................................587 10 (cid:95) Spis tre(cid:316)ci Kup książkęPoleć książkę ROZDZIA(cid:292) 14. Testowanie, debugowanie i wyj(cid:233)tki Testowanie jest ciekawe, natomiast z debugowaniem sytuacja wygl(cid:241)da inaczej. Poniewa(cid:276) nie istnieje kompilator analizuj(cid:241)cy kod przed wykonaniem go przez Pythona, testy s(cid:241) niezb(cid:246)dn(cid:241) cz(cid:246)(cid:264)ci(cid:241) procesu tworzenia oprogramowania. W tym rozdziale opisano pewne cz(cid:246)sto wyst(cid:246)- puj(cid:241)ce problemy zwi(cid:241)zane z testowaniem, debugowaniem i obs(cid:228)ug(cid:241) wyj(cid:241)tków. Nie jest to jednak proste wprowadzenie do programowania sterowanego testami lub korzystania z mo- du(cid:228)u unittest. Zak(cid:228)adamy, (cid:276)e opanowa(cid:228)e(cid:264) ju(cid:276) podstawowe zagadnienia z obszaru testów. 14.1. Testowanie danych wyj(cid:316)ciowych wysy(cid:293)anych do strumienia stdout Problem W programie dzia(cid:228)a metoda, która zwraca dane wyj(cid:264)ciowe do standardowego strumienia wyj(cid:264)cia (sys.stdout). Prawie zawsze oznacza to, (cid:276)e tekst jest wy(cid:264)wietlany na ekranie. Pro- gramista chce napisa(cid:232) test dowodz(cid:241)cy, (cid:276)e dla poprawnych danych wej(cid:264)ciowych wy(cid:264)wietlane s(cid:241) odpowiednie dane wyj(cid:264)ciowe. Rozwi(cid:233)zanie Za pomoc(cid:241) funkcji patch() modu(cid:228)u unittest.mock mo(cid:276)na stosunkowo (cid:228)atwo zasymulowa(cid:232) dzia(cid:228)anie strumienia sys.stdout w jednym te(cid:264)cie, a nast(cid:246)pnie usun(cid:241)(cid:232) u(cid:276)ywany do tego obiekt. Pozwala to unikn(cid:241)(cid:232) stosowania k(cid:228)opotliwych zmiennych tymczasowych i wyciekania symulowanego stanu mi(cid:246)dzy wykonywaniem poszczególnych testów. Przyjrzyj si(cid:246) przyk(cid:228)adowej funkcji z modu(cid:228)u mymodule: # mymodule.py def urlprint(protocol, host, domain): url = {}://{}.{} .format(protocol, host, domain) print(url) Wbudowana funkcja print domy(cid:264)lnie wysy(cid:228)a dane wyj(cid:264)ciowe do strumienia sys.stdout. Aby sprawdzi(cid:232), czy dane wyj(cid:264)ciowe rzeczywi(cid:264)cie trafiaj(cid:241) do tego strumienia, mo(cid:276)na zasymu- lowa(cid:232) jego dzia(cid:228)anie za pomoc(cid:241) obiektu zast(cid:246)pczego, a nast(cid:246)pnie wykorzysta(cid:232) asercje dotycz(cid:241)ce 497 Kup książkęPoleć książkę wykonanych operacji. Metoda patch() modu(cid:228)u unittest.mock pozwala na wygodne zast(cid:246)- powanie obiektów w kontek(cid:264)cie dzia(cid:228)aj(cid:241)cego testu. Natychmiast po zako(cid:254)czeniu testu przy- wracany jest pierwotny stan programu. Oto kod testuj(cid:241)cy modu(cid:228) mymodule: from io import StringIO from unittest import TestCase from unittest.mock import patch import mymodule class TestURLPrint(TestCase): def test_url_gets_to_stdout(self): protocol = http host = www domain = example.com expected_url = {}://{}.{}\n .format(protocol, host, domain) with patch( sys.stdout , new=StringIO()) as fake_out: mymodule.urlprint(protocol, host, domain) self.assertEqual(fake_out.getvalue(), expected_url) Omówienie Funkcja urlprint() przyjmuje trzy argumenty, a test rozpoczyna si(cid:246) od podania fikcyjnych warto(cid:264)ci ka(cid:276)dego z nich. Zmienna expected_url jest ustawiana na (cid:228)a(cid:254)cuch znaków z ocze- kiwanymi danymi wyj(cid:264)ciowymi. Aby uruchomi(cid:232) test, nale(cid:276)y wykorzysta(cid:232) funkcj(cid:246) unittest.mock.patch() jako mened(cid:276)era kon- tekstu w celu zast(cid:241)pienia warto(cid:264)ci sys.stdout obiektem typu StringIO. Zmienna fake_out to tworzony w tym procesie obiekt zast(cid:246)pczy. Mo(cid:276)na go wykorzysta(cid:232) w poleceniu with do przeprowadzenia ró(cid:276)nych testów. Gdy polecenie with ko(cid:254)czy prac(cid:246), funkcja patch() w wygod- ny dla programisty sposób przywraca wszystkie elementy do stanu sprzed uruchomienia testu. Warto zauwa(cid:276)y(cid:232), (cid:276)e w Pythonie niektóre rozszerzenia w j(cid:246)zyku C mog(cid:241) zapisywa(cid:232) dane bezpo(cid:264)rednio do standardowego wyj(cid:264)cia (z pomini(cid:246)ciem strumienia sys.stdout). Ta recep- tura nie pozwala testowa(cid:232) kodu opartego na takich rozszerzeniach, natomiast powinna dzia(cid:228)a(cid:232) poprawnie dla kodu napisanego w samym Pythonie. Je(cid:264)li chcesz przechwytywa(cid:232) operacje wej(cid:264)cia-wyj(cid:264)cia z rozszerze(cid:254) w j(cid:246)zyku C, mo(cid:276)esz otworzy(cid:232) tymczasowy plik i zastosowa(cid:232) sztuczki zwi(cid:241)zane z deskryptorami plików, aby czasowo przekierowywa(cid:232) do tego pliku dane ze standardowego wyj(cid:264)cia. Wi(cid:246)cej informacji na temat przechwytywania operacji wej(cid:264)cia-wyj(cid:264)cia zwi(cid:241)zanych z (cid:228)a(cid:254)cu- chami znaków i obiektami typu StringIO znajdziesz w recepturze 5.6. 14.2. Podstawianie obiektów w testach jednostkowych Problem Programista pisze testy jednostkowe i chce podstawi(cid:232) wybrane obiekty, aby zastosowa(cid:232) asercje zwi(cid:241)zane z wykorzystaniem tych obiektów w czasie testów. Asercje te mog(cid:241) dotyczy(cid:232) wy- wo(cid:228)a(cid:254) z ró(cid:276)nymi parametrami, dost(cid:246)pu do okre(cid:264)lonych atrybutów itd. 498 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę Rozwi(cid:233)zanie W rozwi(cid:241)zaniu tego problemu pomocna b(cid:246)dzie funkcja unittest.mock.patch(). Mo(cid:276)na jej u(cid:276)y(cid:232) jako dekoratora (cho(cid:232) jest to do(cid:264)(cid:232) nietypowe rozwi(cid:241)zanie), mened(cid:276)era kontekstu lub niezale(cid:276)n(cid:241) funkcj(cid:246). Oto przyk(cid:228)adowy kod, w którym u(cid:276)yto jej jako dekoratora: from unittest.mock import patch import example @patch( example.func ) def test1(x, mock_func): example.func(x) # Wywo(cid:225)anie podstawionej funkcji example.func mock_func.assert_called_with(x) Funkcj(cid:246) patch() mo(cid:276)na te(cid:276) wykorzysta(cid:232) jako mened(cid:276)era kontekstu: with patch( example.func ) as mock_func: example.func(x) # Wywo(cid:225)anie podstawionej funkcji example.func mock_func.assert_called_with(x) Ponadto mo(cid:276)na j(cid:241) zastosowa(cid:232) do r(cid:246)cznego podstawiania elementów kodu: p = patch( example.func ) mock_func = p.start() example.func(x) mock_func.assert_called_with(x) p.stop() W razie potrzeby mo(cid:276)na po(cid:228)(cid:241)czy(cid:232) dekoratory i mened(cid:276)ery kontekstu, aby podstawi(cid:232) grup(cid:246) obiektów. Oto przyk(cid:228)ad: @patch( example.func1 ) @patch( example.func2 ) @patch( example.func3 ) def test1(mock1, mock2, mock3): ... def test2(): with patch( example.patch1 ) as mock1,\ patch( example.patch2 ) as mock2,\ patch( example.patch3 ) as mock3: ... Omówienie Funkcja patch() przyjmuje istniej(cid:241)cy obiekt podany za pomoc(cid:241) pe(cid:228)nej nazwy i zast(cid:246)puje go now(cid:241) warto(cid:264)ci(cid:241). Pierwotna warto(cid:264)(cid:232) jest przywracana po zako(cid:254)czeniu pracy funkcji z deko- ratorem lub pracy mened(cid:276)era kontekstu. Domy(cid:264)lnie warto(cid:264)ci s(cid:241) zast(cid:246)powane obiektami typu MagicMock: x = 42 with patch( __main__.x ): ... print(x) ... MagicMock name= x id= 4314230032 x 42 14.2. Podstawianie obiektów w testach jednostkowych (cid:95) 499 Kup książkęPoleć książkę Mo(cid:276)na jednak zast(cid:241)pi(cid:232) warto(cid:264)(cid:232) czym(cid:264) innym, podaj(cid:241)c zast(cid:246)pczy element jako drugi argument funkcji patch(): x 42 with patch( __main__.x , patched_value ): ... print(x) ... patched_value x 42 Obiekty typu MagicMock, standardowo u(cid:276)ywane jako warto(cid:264)ci zast(cid:246)pcze, maj(cid:241) na(cid:264)ladowa(cid:232) prac(cid:246) jednostek wywo(cid:228)ywalnych i obiektów. Rejestruj(cid:241) informacje na temat u(cid:276)ywania i po- zwalaj(cid:241) stosowa(cid:232) asercje. Oto przyk(cid:228)ad: from unittest.mock import MagicMock m = MagicMock(return_value = 10) m(1, 2, debug=True) 10 m.assert_called_with(1, 2, debug=True) m.assert_called_with(1, 2) Traceback (most recent call last): File stdin , line 1, in module File .../unittest/mock.py , line 726, in assert_called_with raise AssertionError(msg) AssertionError: Expected call: mock(1, 2) Actual call: mock(1, 2, debug=True) m.upper.return_value = WITAJ m.upper( witaj ) WITAJ assert m.upper.called m.split.return_value = [ witaj , (cid:321)wiecie ] m.split( witaj (cid:321)wiecie ) [ witaj , (cid:321)wiecie ] m.split.assert_called_with( witaj (cid:321)wiecie ) m[ blah ] MagicMock name= mock.__getitem__() id= 4314412048 m.__getitem__.called True m.__getitem__.assert_called_with( blah ) Zwykle operacje tego rodzaju przeprowadza si(cid:246) w testach jednostkowych. Za(cid:228)ó(cid:276)my, (cid:276)e u(cid:276)y- wasz nast(cid:246)puj(cid:241)cej funkcji: # example.py from urllib.request import urlopen import csv def dowprices(): u = urlopen( http://finance.yahoo.com/d/quotes.csv?s=@^DJI f=sl1 ) lines = (line.decode( utf-8 ) for line in u) rows = (row for row in csv.reader(lines) if len(row) == 2) prices = { name:float(price) for name, price in rows } return prices 500 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę Przy pobieraniu danych z internetu i ich parsowaniu funkcja ta u(cid:276)ywa standardowo wywo- (cid:228)ania urlopen(). W testach jednostkowych mo(cid:276)esz jednak udost(cid:246)pni(cid:232) samodzielnie opraco- wany przewidywalny zbiór danych. Oto przyk(cid:228)ad oparty na podstawianiu danych: import unittest from unittest.mock import patch import io import example sample_data = io.BytesIO(b \ IBM ,91.1\r AA ,13.25\r MSFT ,27.72\r \r ) class Tests(unittest.TestCase): @patch( example.urlopen , return_value=sample_data) def test_dowprices(self, mock_urlopen): p = example.dowprices() self.assertTrue(mock_urlopen.called) self.assertEqual(p, { IBM : 91.1, AA : 13.25, MSFT : 27.72}) if __name__ == __main__ : unittest.main() W tym kodzie funkcja urlopen() z modu(cid:228)u example jest zast(cid:246)powana obiektem zast(cid:246)pczym, który zwraca obiekt BytesIO() zawieraj(cid:241)cy przyk(cid:228)adowe dane. Wa(cid:276)nym, a przy tym trudnym do zauwa(cid:276)enia aspektem przedstawionego testu jest to, (cid:276)e podstawiana jest funkcja example.urlopen, a nie urllib.request.urlopen. Przy podsta- wianiu elementów trzeba stosowa(cid:232) nazwy w takiej postaci, w jakiej wyst(cid:246)puj(cid:241) w testowanym kodzie. Poniewa(cid:276) w przyk(cid:228)adowym kodzie pojawia si(cid:246) polecenie from urllib.request import urlopen, funkcja urlopen() u(cid:276)ywana w funkcji dowprices() znajduje si(cid:246) w module example. W tej recepturze przedstawiono tylko niewielk(cid:241) cz(cid:246)(cid:264)(cid:232) mo(cid:276)liwo(cid:264)ci modu(cid:228)u unittest.mock. Aby zapozna(cid:232) si(cid:246) z bardziej zaawansowanymi mechanizmami, koniecznie zajrzyj do oficjalnej dokumentacji (http://docs.python.org/3/library/unittest.mock). 14.3. Sprawdzanie wyst(cid:233)pienia wyj(cid:233)tków w testach jednostkowych Problem Programista chce napisa(cid:232) testy jednostkowe, które w elegancki sposób sprawdzaj(cid:241), czy wy- st(cid:241)pi(cid:228) wyj(cid:241)tek. Rozwi(cid:233)zanie Aby sprawdzi(cid:232) wyst(cid:241)pienie wyj(cid:241)tków, nale(cid:276)y zastosowa(cid:232) metod(cid:246) assertRaises(). Je(cid:264)li chcesz ustali(cid:232), czy funkcja zg(cid:228)osi(cid:228)a wyj(cid:241)tek ValueError, zastosuj nast(cid:246)puj(cid:241)cy kod: 14.3. Sprawdzanie wyst(cid:233)pienia wyj(cid:233)tków w testach jednostkowych (cid:95) 501 Kup książkęPoleć książkę import unittest # Prosta przyk(cid:225)adowa funkcja def parse_int(s): return int(s) class TestConversion(unittest.TestCase): def test_bad_int(self): self.assertRaises(ValueError, parse_int, N/A ) Je(cid:264)li chcesz sprawdzi(cid:232) warto(cid:264)(cid:232) wyj(cid:241)tku, musisz zastosowa(cid:232) inne podej(cid:264)cie. Oto przyk(cid:228)ad: import errno class TestIO(unittest.TestCase): def test_file_not_found(self): try: f = open( /file/not/found ) except IOError as e: self.assertEqual(e.errno, errno.ENOENT) else: self.fail( Wyj(cid:238)tek IOError nie wyst(cid:238)pi(cid:298) ) Omówienie Metoda assertRaises() umo(cid:276)liwia wygodne sprawdzenie wyst(cid:241)pienia wyj(cid:241)tku. Cz(cid:246)stym b(cid:228)(cid:246)dem jest samodzielne próbowanie wykrywania wyj(cid:241)tków w pisanych testach. Oto przyk(cid:228)ad: class TestConversion(unittest.TestCase): def test_bad_int(self): try: r = parse_int( N/A ) except ValueError as e: self.assertEqual(type(e), ValueError) Problem z tym podej(cid:264)ciem polega na tym, (cid:276)e (cid:228)atwo jest zapomnie(cid:232) o warunkach brzegowych, np. o sytuacji, gdy w kodzie w ogóle nie wyst(cid:241)pi(cid:228) wyj(cid:241)tek. Aby uwzgl(cid:246)dni(cid:232) t(cid:246) sytuacj(cid:246), trzeba doda(cid:232) dodatkowy warunek: class TestConversion(unittest.TestCase): def test_bad_int(self): try: r = parse_int( N/A ) except ValueError as e: self.assertEqual(type(e), ValueError) else: self.fail( Wyj(cid:238)tek ValueError nie wyst(cid:238)pi(cid:298) ) Metoda assertRaises() uwzgl(cid:246)dnia takie sytuacje, dlatego nale(cid:276)y korzysta(cid:232) w(cid:228)a(cid:264)nie z niej. Wad(cid:241) metody assertRaises() jest to, (cid:276)e nie umo(cid:276)liwia okre(cid:264)lenia warto(cid:264)ci utworzonego obiektu wyj(cid:241)tku. Warto(cid:264)(cid:232) t(cid:246) trzeba sprawdzi(cid:232) r(cid:246)cznie. Rozwi(cid:241)zaniem po(cid:264)rednim jest zasto- sowanie metody assertRaisesRegex(), która umo(cid:276)liwia sprawdzenie, czy wyj(cid:241)tek wyst(cid:241)pi(cid:228), a jednocze(cid:264)nie porównuje (cid:228)a(cid:254)cuchow(cid:241) reprezentacj(cid:246) wyj(cid:241)tku z wyra(cid:276)eniem regularnym. Oto przyk(cid:228)ad: class TestConversion(unittest.TestCase): def test_bad_int(self): self.assertRaisesRegex(ValueError, invalid literal .* , parse_int, N/A ) 502 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę Ma(cid:228)o znan(cid:241) cech(cid:241) metod assertRaises() i assertRaisesRegex() jest to, (cid:276)e mo(cid:276)na z nich korzysta(cid:232) jak z mened(cid:276)erów kontekstu: class TestConversion(unittest.TestCase): def test_bad_int(self): with self.assertRaisesRegex(ValueError, invalid literal .* ): r = parse_int( N/A ) Ta posta(cid:232) mo(cid:276)e okaza(cid:232) si(cid:246) przydatna, je(cid:264)li test obejmuje kilka etapów (np. etap konfiguracji) oprócz samego wywo(cid:228)ania jednostki wywo(cid:228)ywalnej. 14.4. Zapisywanie danych wyj(cid:316)ciowych testu w pliku Problem Programista chce, aby dane wyj(cid:264)ciowe testu by(cid:228)y zapisywane w pliku, a nie przekazywane do standardowego wyj(cid:264)cia. Rozwi(cid:233)zanie Cz(cid:246)sto stosowan(cid:241) technik(cid:241) przeprowadzania testów jednostkowych jest umieszczanie krót- kiego fragmentu kodu w ko(cid:254)cowej cz(cid:246)(cid:264)ci pliku z kodem testu: import unittest class MyTest(unittest.TestCase): ... if __name__ == __main__ : unittest.main() Dzi(cid:246)ki temu plik z kodem testu jest wykonywalny i wy(cid:264)wietla wyniki przeprowadzenia testu w standardowym wyj(cid:264)ciu. Je(cid:264)li chcesz przekierowa(cid:232) dane wyj(cid:264)ciowe gdzie indziej, rozwi(cid:254) wywo(cid:228)anie main() i napisz w(cid:228)asn(cid:241) funkcj(cid:246) main(): import sys def main(out=sys.stderr, verbosity=2): loader = unittest.TestLoader() suite = loader.loadTestsFromModule(sys.modules[__name__]) unittest.TextTestRunner(out,verbosity=verbosity).run(suite) if __name__ == __main__ : with open( testing.out , w ) as f: main(f) Omówienie Ciekawym aspektem tej receptury jest nie tyle przekierowywanie wyników testu do pliku, co fakt, (cid:276)e wykonanie tego zadania pozwala zrozumie(cid:232) dzia(cid:228)anie wewn(cid:246)trznych mechanizmów modu(cid:228)u unittest. Na podstawowym poziomie modu(cid:228) unittest najpierw tworzy zestaw testów. Sk(cid:228)ada si(cid:246) on z ró(cid:276)nych zdefiniowanych metod testowych. Po przygotowaniu zestawu wykonywane s(cid:241) testy wchodz(cid:241)ce w jego sk(cid:228)ad. 14.4. Zapisywanie danych wyj(cid:316)ciowych testu w pliku (cid:95) 503 Kup książkęPoleć książkę Obie wymienione cz(cid:246)(cid:264)ci testów jednostkowych s(cid:241) niezale(cid:276)ne od siebie. Tworzony w rozwi(cid:241)- zaniu obiekt typu unittest.TestLoader s(cid:228)u(cid:276)y do przygotowywania zestawu testów. Metoda loadTestsFromModule() to jedna z kilku metod do wczytywania testów. Tu metoda ta szuka w module klas TestCase i wczytuje z nich metody testowe. Je(cid:264)li potrzebujesz wi(cid:246)kszej kon- troli, mo(cid:276)esz wykorzysta(cid:232) metod(cid:246) loadTestsFromTestCase() (nie jest u(cid:276)ywana w kodzie) do pobrania metod testowych z konkretnych klas pochodnych od klasy TestCase. Klasa TextTestRunner to przyk(cid:228)adowa klasa przeprowadzaj(cid:241)ca testy. G(cid:228)ównym jej zadaniem jest wykonanie testów z zestawu. Klasa ta jest powi(cid:241)zana z funkcj(cid:241) unittest.main(). Tu skonfi- gurowano niskopoziomowe aspekty tej klasy — okre(cid:264)lono plik na dane wyj(cid:264)ciowe i zwi(cid:246)k- szono poziom szczegó(cid:228)owo(cid:264)ci rejestrowanych danych. Cho(cid:232) ta receptura zawiera tylko kilka wierszy kodu, pomaga zrozumie(cid:232), jak dostosowa(cid:232) dzia- (cid:228)anie modu(cid:228)u unittest do w(cid:228)asnych potrzeb. Aby zmieni(cid:232) sposób tworzenia zestawu testów, nale(cid:276)y wykona(cid:232) odpowiednie operacje za pomoc(cid:241) klasy TestLoader. Je(cid:264)li chcesz zmodyfi- kowa(cid:232) sposób przeprowadzania testów, utwórz niestandardow(cid:241) klas(cid:246) do uruchamiania testów, dzia(cid:228)aj(cid:241)c(cid:241) podobnie jak TextTestRunner. Omawianie tych zagadnie(cid:254) wykracza poza zakres tej ksi(cid:241)(cid:276)ki. Dok(cid:228)adny przegl(cid:241)d potrzebnych protoko(cid:228)ów znajdziesz w dokumentacji modu(cid:228)u unittest. 14.5. Pomijanie testów lub przewidywanie ich niepowodzenia Problem Programista chce ignorowa(cid:232) lub oznacza(cid:232) w testach jednostkowych wybrane testy, które zgodnie z oczekiwaniami maj(cid:241) zako(cid:254)czy(cid:232) si(cid:246) niepowodzeniem. Rozwi(cid:233)zanie Modu(cid:228) unittest udost(cid:246)pnia dekoratory, które mo(cid:276)na zastosowa(cid:232) do wybranych metod te- stowych w celu uzyskania kontroli nad ich przebiegiem. Oto przyk(cid:228)ad: import unittest import os import platform class Tests(unittest.TestCase): def test_0(self): self.assertTrue(True) @unittest.skip( Test pomini(cid:258)to ) def test_1(self): self.fail( Powinien zako(cid:300)czy(cid:240) si(cid:258) niepowodzeniem! ) @unittest.skipIf(os.name== posix , Nieobs(cid:298)ugiwane w systemach uniksowych ) def test_2(self): import winreg @unittest.skipUnless(platform.system() == Darwin , Test dla systemu Mac OS ) def test_3(self): self.assertTrue(True) 504 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę @unittest.expectedFailure def test_4(self): self.assertEqual(2+2, 5) if __name__ == __main__ : unittest.main() Je(cid:264)li uruchomisz ten test na komputerze z systemem Mac OS, otrzymasz nast(cid:246)puj(cid:241)ce dane wyj(cid:264)ciowe: bash python3 testsample.py -v test_0 (__main__.Tests) ... ok test_1 (__main__.Tests) ... skipped Test pomini(cid:258)to test_2 (__main__.Tests) ... skipped Nieobs(cid:298)ugiwane w systemach uniksowych test_3 (__main__.Tests) ... ok test_4 (__main__.Tests) ... expected failure ---------------------------------------------------------------------- Ran 5 tests in 0.002s OK (skipped=2, expected failures=1) Omówienie Dekorator skip() umo(cid:276)liwia pomini(cid:246)cie testu, którego nie chcesz przeprowadza(cid:232). Dekoratory skipIf() i skipUnless() mog(cid:241) by(cid:232) przydatne do pisania testów, które dotycz(cid:241) tylko okre- (cid:264)lonych systemów operacyjnych lub wersji Pythona albo zale(cid:276)(cid:241) od innego oprogramowania. Za pomoc(cid:241) dekoratora @expectedFailure mo(cid:276)esz oznaczy(cid:232) testy, o których wiesz, (cid:276)e po- winny zako(cid:254)czy(cid:232) si(cid:246) niepowodzeniem (i nie chcesz, aby platforma testowa generowa(cid:228)a do- datkowe informacje na temat tych testów). Dekoratory przeznaczone do pomijania metod mo(cid:276)na te(cid:276) stosowa(cid:232) do ca(cid:228)ych klas testowych. Oto przyk(cid:228)ad: @unittest.skipUnless(platform.system() == Darwin , Testy tylko dla systemu Mac OS ) class DarwinTests(unittest.TestCase): ... 14.6. Obs(cid:293)uga wielu wyj(cid:233)tków Problem Dany fragment kodu mo(cid:276)e zg(cid:228)asza(cid:232) ró(cid:276)ne wyj(cid:241)tki. Programista chce uwzgl(cid:246)dni(cid:232) wszystkie mo(cid:276)liwe wyj(cid:241)tki bez tworzenia powtarzaj(cid:241)cych si(cid:246) fragmentów lub d(cid:228)ugich, skomplikowa- nych bloków kodu. Rozwi(cid:233)zanie Je(cid:264)li do obs(cid:228)ugi ró(cid:276)nych wyj(cid:241)tków mo(cid:276)na wykorzysta(cid:232) jeden blok kodu, wyj(cid:241)tki mo(cid:276)na po- grupowa(cid:232) za pomoc(cid:241) krotki: try: client_obj.get_url(url) except (URLError, ValueError, SocketTimeout): client_obj.remove_url(url) 14.6. Obs(cid:293)uga wielu wyj(cid:233)tków (cid:95) 505 Kup książkęPoleć książkę W tym przyk(cid:228)adzie metoda remove_url() jest wywo(cid:228)ywana, gdy wyst(cid:241)pi jeden z wymienionych wyj(cid:241)tków. Je(cid:264)li jeden z wyj(cid:241)tków trzeba obs(cid:228)u(cid:276)y(cid:232) inaczej, nale(cid:276)y umie(cid:264)ci(cid:232) go w klauzuli except: try: client_obj.get_url(url) except (URLError, ValueError): client_obj.remove_url(url) except SocketTimeout: client_obj.handle_url_timeout(url) Wyj(cid:241)tki cz(cid:246)sto s(cid:241) grupowane w hierarchie dziedziczenia. Wtedy wszystkie wyj(cid:241)tki mo(cid:276)na przechwytywa(cid:232) przy u(cid:276)yciu klasy bazowej. Zamiast pisa(cid:232) nast(cid:246)puj(cid:241)cy kod: try: f = open(filename) except (FileNotFoundError, PermissionError): ... mo(cid:276)na zastosowa(cid:232) polecenie except w poni(cid:276)szy sposób: try: f = open(filename) except OSError: ... To rozwi(cid:241)zanie dzia(cid:228)a, poniewa(cid:276) OSError to klasa bazowa wspólna dla wyj(cid:241)tków FileNot (cid:180)FoundError i PermissionError. Omówienie Cho(cid:232) poni(cid:276)sza technika dotyczy nie tylko obs(cid:228)ugi wielu wyj(cid:241)tków, warto zauwa(cid:276)y(cid:232), (cid:276)e do obs(cid:228)ugi zg(cid:228)aszanych wyj(cid:241)tków mo(cid:276)na te(cid:276) wykorzysta(cid:232) s(cid:228)owo kluczowe as: try: f = open(filename) except OSError as e: if e.errno == errno.ENOENT: logger.error( Pliku nie znaleziono ) elif e.errno == errno.EACCES: logger.error( Odmowa uprawnie(cid:300) ) else: logger.error( Nieoczekiwany b(cid:298)(cid:238)d: d , e.errno) W tym przyk(cid:228)adzie zmienna e zawiera obiekt zg(cid:228)aszaj(cid:241)cy wyj(cid:241)tek OSError. Jest to przydatne, je(cid:264)li trzeba zbada(cid:232) wyj(cid:241)tek (np. obs(cid:228)u(cid:276)y(cid:232) go na podstawie warto(cid:264)ci dodatkowego kodu stanu). Pami(cid:246)taj, (cid:276)e klauzule except s(cid:241) sprawdzane w kolejno(cid:264)ci wyst(cid:246)powania i wykonywany jest kod z pierwszej pasuj(cid:241)cej klauzuli. Nie jest to idealne rozwi(cid:241)zanie, jednak mo(cid:276)na (cid:228)atwo utworzy(cid:232) kod, w którym do wyj(cid:241)tku pasuje kilka klauzul except: f = open( Brak ) Traceback (most recent call last): File stdin , line 1, in module FileNotFoundError: [Errno 2] No such file or directory: Brak try: ... f = open( Brak ) ... except OSError: ... print( Niepowodzenie ) ... except FileNotFoundError: ... print( Pliku nie znaleziono ) ... Niepowodzenie 506 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę Klauzula except FileNotFoundError nie jest uruchamiana, poniewa(cid:276) wyj(cid:241)tek OSError jest ogólniejszy, pasuje do wyj(cid:241)tku FileNotFoundError i znajduje si(cid:246) pierwszy na li(cid:264)cie. Oto wskazówka dotycz(cid:241)ca debugowania — je(cid:264)li nie znasz hierarchii klas obejmuj(cid:241)cej dany wyj(cid:241)tek, mo(cid:276)esz j(cid:241) szybko wy(cid:264)wietli(cid:232), sprawdzaj(cid:241)c warto(cid:264)(cid:232) atrybutu __mro__ tego wyj(cid:241)tku: FileNotFoundError.__mro__ ( class FileNotFoundError , class OSError , class Exception , class BaseException , class object ) W poleceniu except mo(cid:276)na poda(cid:232) dowoln(cid:241) z wymienionych klas a(cid:276) do BaseException. 14.7. Przechwytywanie wszystkich wyj(cid:233)tków Problem Programista chce napisa(cid:232) kod, który przechwytuje wszystkie wyj(cid:241)tki. Rozwi(cid:233)zanie Aby przechwytywa(cid:232) wszystkie wyj(cid:241)tki, nale(cid:276)y napisa(cid:232) blok obs(cid:228)ugi wyj(cid:241)tków typu Exception: try: ... except Exception as e: ... log( Powód: , e) # To wa(cid:298)ne! Ten kod przechwytuje wszystkie wyj(cid:241)tki oprócz SystemExit, KeyboardInterrupt i GeneratorExit. Je(cid:264)li chcesz przechwytywa(cid:232) tak(cid:276)e te wyj(cid:241)tki, zmie(cid:254) typ Exception na BaseException. Omówienie Przechwytywanie wszystkich wyj(cid:241)tków jest czasem stosowane jako u(cid:228)atwienie przez pro- gramistów, którzy nie potrafi(cid:241) zapami(cid:246)ta(cid:232) ka(cid:276)dego wyj(cid:241)tku mo(cid:276)liwego w skomplikowanej operacji. Dlatego je(cid:264)li nie zachowasz ostro(cid:276)no(cid:264)ci, jest to (cid:264)wietny sposób na utworzenie kodu, którego debugowanie b(cid:246)dzie bardzo trudne. Je(cid:276)eli zdecydujesz si(cid:246) przechwytywa(cid:232) wszystkie wyj(cid:241)tki, koniecznie rejestruj lub wy(cid:264)wietlaj powód wyst(cid:241)pienia wyj(cid:241)tku (mo(cid:276)esz zapisywa(cid:232) przyczyn(cid:246) w pliku dziennika, wy(cid:264)wietla(cid:232) na ekranie komunikat o b(cid:228)(cid:246)dzie itd.). W przeciwnym razie b(cid:246)dziesz mia(cid:228) powa(cid:276)ne trudno(cid:264)ci z ustaleniem przyczyny problemów. Przyjrzyj si(cid:246) nast(cid:246)puj(cid:241)cemu przyk(cid:228)adowi: def parse_int(s): try: n = int(v) except Exception: print( Nieudane parsowanie ) Je(cid:264)li uruchomisz t(cid:246) funkcj(cid:246), uzyskasz nast(cid:246)puj(cid:241)ce dane: parse_int( n/a ) Nieudane parsowanie parse_int( 42 ) Nieudane parsowanie 14.7. Przechwytywanie wszystkich wyj(cid:233)tków (cid:95) 507 Kup książkęPoleć książkę Mo(cid:276)esz si(cid:246) zastanawia(cid:232), dlaczego kod nie dzia(cid:228)a. Teraz za(cid:228)ó(cid:276)my, (cid:276)e funkcja wygl(cid:241)da tak: def parse_int(s): try: n = int(v) except Exception as e: print( Nieudane parsowanie ) print( Powód: , e) Tym razem uzyskasz nast(cid:246)puj(cid:241)ce dane, informuj(cid:241)ce, (cid:276)e programista pope(cid:228)ni(cid:228) b(cid:228)(cid:241)d: parse_int( 42 ) Nieudane parsowanie Powód: global name v is not defined Zwykle lepiej jest obs(cid:228)ugiwa(cid:232) wyj(cid:241)tki konkretnego typu. Je(cid:264)li jednak musisz przechwytywa(cid:232) je wszystkie, zapewnij sobie dobre informacje diagnostyczne lub przeka(cid:276) wyj(cid:241)tek, aby nie utraci(cid:232) danych o przyczynie b(cid:228)(cid:246)du. 14.8. Tworzenie niestandardowych wyj(cid:233)tków Problem Programista tworzy aplikacj(cid:246) i chce umie(cid:264)ci(cid:232) niskopoziomowe wyj(cid:241)tki w niestandardowych, które b(cid:246)d(cid:241) przekazywa(cid:228)y wi(cid:246)cej informacji w kontek(cid:264)cie programu. Rozwi(cid:233)zanie Tworzenie nowych wyj(cid:241)tków jest (cid:228)atwe. Wystarczy zdefiniowa(cid:232) je jako klasy pochodne od klasy Exception (lub od jednego z innych istniej(cid:241)cych typów wyj(cid:241)tków, je(cid:264)li ma to wi(cid:246)cej sensu). Np. w kodzie dotycz(cid:241)cym sieci mo(cid:276)na zdefiniowa(cid:232) niestandardowe wyj(cid:241)tki w nast(cid:246)- puj(cid:241)cy sposób: class NetworkError(Exception): pass class HostnameError(NetworkError): pass class TimeoutError(NetworkError): pass class ProtocolError(NetworkError): pass U(cid:276)ytkownicy mog(cid:241) nast(cid:246)pnie korzysta(cid:232) z tych wyj(cid:241)tków w standardowy sposób. Oto przyk(cid:228)ad: try: msg = s.recv() except TimeoutError as e: ... except ProtocolError as e: ... 508 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę Omówienie Niestandardowe klasy wyj(cid:241)tków prawie zawsze powinny dziedziczy(cid:232) po wbudowanej klasie Exception lub po lokalnie zdefiniowanej klasie wyj(cid:241)tku podstawowego, która sama jest po- chodna od Exception. Cho(cid:232) wszystkie wyj(cid:241)tki dziedzicz(cid:241) te(cid:276) po klasie BaseException, nie nale(cid:276)y jej stosowa(cid:232) jako klasy bazowej dla nowych wyj(cid:241)tków. Klasa BaseException jest zare- zerwowana dla wyj(cid:241)tków zwi(cid:241)zanych z wyj(cid:264)ciem z systemu (takich jak KeyboardInterrupt i SystemExit) oraz innych, które sygnalizuj(cid:241) aplikacji, (cid:276)e ma zako(cid:254)czy(cid:232) prac(cid:246). Dlatego wy- j(cid:241)tki tego rodzaju nie s(cid:241) przeznaczone do przechwytywania. Je(cid:264)li zastosujesz si(cid:246) do tej kon- wencji i wykorzystasz klas(cid:246) BaseException jako bazow(cid:241), niestandardowe wyj(cid:241)tki nie b(cid:246)d(cid:241) przechwytywane — zostan(cid:241) uznane za sygna(cid:228) natychmiastowego zamkni(cid:246)cia aplikacji! Tworzenie w aplikacji niestandardowych wyj(cid:241)tków i stosowanie ich w przedstawiony sposób sprawia, (cid:276)e kod jest bardziej zrozumia(cid:228)y dla jego czytelników. W trakcie projektowania takiego kodu nale(cid:276)y zastanowi(cid:232) si(cid:246) nad pogrupowaniem niestandardowych wyj(cid:241)tków za pomoc(cid:241) dziedziczenia. W skomplikowanych aplikacjach sensowne mo(cid:276)e by(cid:232) utworzenie dodatkowych klas bazowych, (cid:228)(cid:241)cz(cid:241)cych ró(cid:276)ne klasy wyj(cid:241)tków. Dzi(cid:246)ki temu u(cid:276)ytkownik mo(cid:276)e przechwy- tywa(cid:232) (cid:264)ci(cid:264)le okre(cid:264)lone b(cid:228)(cid:246)dy: try: s.send(msg) except ProtocolError: ... a tak(cid:276)e bardziej ogólne grupy b(cid:228)(cid:246)dów: try: s.send(msg) except NetworkError: ... Je(cid:264)li chcesz zdefiniowa(cid:232) nowy wyj(cid:241)tek przes(cid:228)aniaj(cid:241)cy metod(cid:246) __init__() z klasy Exception, koniecznie dodaj wywo(cid:228)anie Exception.__init__() ze wszystkimi przekazanymi argu- mentami. Oto przyk(cid:228)ad: class CustomError(Exception): def __init__(self, message, status): super().__init__(message, status) self.message = message self.status = status Mo(cid:276)e wygl(cid:241)da to dziwnie, jednak klasa Exception domy(cid:264)lnie przyjmuje wszystkie przeka- zane argumenty i zapisuje je w postaci krotki w atrybucie .args. Ró(cid:276)ne inne biblioteki i ele- menty Pythona dzia(cid:228)aj(cid:241) tak, jakby wszystkie wyj(cid:241)tki udost(cid:246)pnia(cid:228)y atrybut .args, dlatego je(cid:264)li pominiesz wspomniany krok, mo(cid:276)e si(cid:246) okaza(cid:232), (cid:276)e w pewnych sytuacjach nowy wyj(cid:241)tek nie b(cid:246)dzie dzia(cid:228)a(cid:228) poprawnie. Aby zrozumie(cid:232), jak stosowa(cid:232) atrybut .args, przyjrzyj si(cid:246) poni(cid:276)szej interaktywnej sesji, w której wykorzystano wbudowany wyj(cid:241)tek RuntimeError. Zwró(cid:232) uwag(cid:246) na to, (cid:276)e w poleceniu raise mo(cid:276)na poda(cid:232) dowoln(cid:241) liczb(cid:246) argumentów: try: ... raise RuntimeError( Niepowodzenie ) ... except RuntimeError as e: ... print(e.args) ... ( Niepowodzenie ,) try: 14.8. Tworzenie niestandardowych wyj(cid:233)tków (cid:95) 509 Kup książkęPoleć książkę ... raise RuntimeError( Niepowodzenie , 42, spam ) ... except RuntimeError as e: ... print(e.args) ... ( Niepowodzenie , 42, spam ) Wi(cid:246)cej informacji na temat tworzenia w(cid:228)asnych wyj(cid:241)tków znajdziesz w dokumentacji Pythona (http://docs.python.org/3/tutorial/errors.html). 14.9. Zg(cid:293)aszanie wyj(cid:233)tku w odpowiedzi na wyst(cid:233)pienie innego wyj(cid:233)tku Problem Programista zamierza zg(cid:228)asza(cid:232) wyj(cid:241)tek w odpowiedzi na przechwycenie innego wyj(cid:241)tku. Chce przy tym zapisywa(cid:232) w (cid:264)ladzie b(cid:228)(cid:246)du informacje o obu wyj(cid:241)tkach. Rozwi(cid:233)zanie Aby po(cid:228)(cid:241)czy(cid:232) wyj(cid:241)tki w (cid:228)a(cid:254)cuch, zastosuj polecenie raise from zamiast prostego wywo(cid:228)ania raise. Dzi(cid:246)ki temu otrzymasz informacje o obu b(cid:228)(cid:246)dach. Oto przyk(cid:228)ad: def example(): ... try: ... int( Brak ) ... except ValueError as e: ... raise RuntimeError( B(cid:298)(cid:238)d parsowania ) from e... example() Traceback (most recent call last): File stdin , line 3, in example ValueError: invalid literal for int() with base 10: Brak The above exception was the direct cause of the following exception: Traceback (most recent call last): File stdin , line 1, in module File stdin , line 5, in example RuntimeError: B(cid:298)(cid:238)d parsowania W (cid:264)ladzie b(cid:228)(cid:246)du wida(cid:232), (cid:276)e przechwytywane s(cid:241) oba wyj(cid:241)tki. Aby przechwyci(cid:232) wyj(cid:241)tek, nale(cid:276)y zastosowa(cid:232) standardowe polecenie except. Dodatkowo mo(cid:276)na jednak sprawdzi(cid:232) warto(cid:264)(cid:232) atrybutu __cause__ obiektu wyj(cid:241)tku, aby w razie potrzeby ustali(cid:232) wyj(cid:241)tki z ich (cid:228)a(cid:254)cucha. Oto przyk(cid:228)ad: try: example() except RuntimeError as e: print( Nie zadzia(cid:298)a(cid:298)o: , e) if e.__cause__: print( Powód: , e.__cause__) 510 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę (cid:227)a(cid:254)cuch wyj(cid:241)tków powstaje bez ingerencji programisty, gdy w bloku except zostaje zg(cid:228)oszony inny wyj(cid:241)tek: def example2(): ... try: ... int( Brak ) ... except ValueError as e: ... print( Nieudane parsowanie: , err) ... example2() Traceback (most recent call last): File stdin , line 3, in example2 ValueError: invalid literal for int() with base 10: Brak During handling of the above exception, another exception occurred: Traceback (most recent call last): File stdin , line 1, in module File stdin , line 5, in example2 NameError: global name err is not defined W tym przyk(cid:228)adzie dost(cid:246)pne s(cid:241) dane na temat obu wyj(cid:241)tków, jednak ich interpretacja jest odmienna. Tu wyj(cid:241)tek NameError jest zg(cid:228)aszany w wyniku b(cid:228)(cid:246)du programisty, a nie bezpo- (cid:264)rednio w odpowiedzi na b(cid:228)(cid:241)d parsowania. W takiej sytuacji atrybut __cause__ wyj(cid:241)tku nie jest ustawiany. Zamiast tego atrybut __context__ zostaje ustawiony na poprzedni wyj(cid:241)tek. Je(cid:264)li z jakich(cid:264) powodów nie chcesz (cid:228)(cid:241)czy(cid:232) wyj(cid:241)tków w (cid:228)a(cid:254)cuch, zastosuj polecenie raise from None: def example3(): ... try: ... int( Brak ) ... except ValueError: ... raise RuntimeError( B(cid:298)(cid:238)d parsowania ) from None... example3() Traceback (most recent call last): File stdin , line 1, in module File stdin , line 5, in example3 RuntimeError: B(cid:298)(cid:238)d parsowania Omówienie W trakcie projektowania kodu nale(cid:276)y zwróci(cid:232) uwag(cid:246) na stosowanie polecenia raise w in- nych blokach except. Zwykle takie polecenie nale(cid:276)y zmieni(cid:232) na raise from. Preferowany powinien by(cid:232) kod w nast(cid:246)puj(cid:241)cej postaci: try: ... except SomeException as e: raise DifferentException() from e Wynika to z tego, (cid:276)e taki kod automatycznie (cid:228)(cid:241)czy w (cid:228)a(cid:254)cuch przyczyny b(cid:228)(cid:246)dów. Wyj(cid:241)tek DifferentException jest tu zg(cid:228)aszany bezpo(cid:264)rednio w odpowiedzi na wyj(cid:241)tek SomeException. Ta zale(cid:276)no(cid:264)(cid:232) jest bezpo(cid:264)rednio widoczna w (cid:264)ladzie b(cid:228)(cid:246)du. 14.9. Zg(cid:293)aszanie wyj(cid:233)tku w odpowiedzi na wyst(cid:233)pienie innego wyj(cid:233)tku (cid:95) 511 Kup książkęPoleć książkę Je(cid:264)li piszesz kod w poni(cid:276)szej postaci, wyj(cid:241)tki te(cid:276) s(cid:241) (cid:228)(cid:241)czone w (cid:228)a(cid:254)cuch, jednak cz(cid:246)sto nie wiadomo, czy powsta(cid:228) on celowo, czy w wyniku nieoczekiwanego b(cid:228)(cid:246)du w kodzie: try: ... except SomeException: raise DifferentException() Polecenie raise from pozwala jednoznacznie okre(cid:264)li(cid:232), (cid:276)e programista chcia(cid:228) zg(cid:228)osi(cid:232) drugi wyj(cid:241)tek. Staraj si(cid:246) unika(cid:232) blokowania informacji o wyj(cid:241)tkach, jak zrobiono to w poprzednim przyk(cid:228)adzie. Cho(cid:232) blokowanie komunikatów mo(cid:276)e prowadzi(cid:232) do powstawania krótszych (cid:264)ladów b(cid:228)(cid:246)dów, powoduje te(cid:276) usuni(cid:246)cie informacji, które mog(cid:241) okaza(cid:232) si(cid:246) przydatne w trakcie debugowania. Cz(cid:246)sto najlepiej jest zachowa(cid:232) tak du(cid:276)o danych, jak to tylko mo(cid:276)liwe. 14.10. Ponowne zg(cid:293)aszanie ostatniego wyj(cid:233)tku Problem Programista przechwyci(cid:228) wyj(cid:241)tek w bloku except i teraz chce go ponownie zg(cid:228)osi(cid:232). Rozwi(cid:233)zanie Wystarczy zastosowa(cid:232) samo polecenie raise. Oto przyk(cid:228)ad: def example(): ... try: ... int( Brak ) ... except ValueError: ... print( Nie zadzia(cid:298)a(cid:298)o ) ... raise ... example() Nie zadzia(cid:298)a(cid:298)o Traceback (most recent call last): File stdin , line 1, in module File stdin , line 3, in example ValueError: invalid literal for int() with base 10: Brak Omówienie Ten problem powstaje, gdy w odpowiedzi na wyst(cid:241)pienie wyj(cid:241)tku musisz podj(cid:241)(cid:232) pewne dzia(cid:228)ania (np. zarejestrowa(cid:232) operacje, wykona(cid:232) zadania porz(cid:241)dkuj(cid:241)ce), a nast(cid:246)pnie przekaza(cid:232) wyj(cid:241)tek dalej. Przedstawion(cid:241) technik(cid:246) bardzo cz(cid:246)sto stosuje si(cid:246) w blokach obs(cid:228)ugi przechwy- tuj(cid:241)cych wszystkie wyj(cid:241)tki: try: ... except Exception as e: # Przetwarzanie informacji o wyj(cid:261)tku ... # Przekazywanie wyj(cid:261)tku raise 512 (cid:95) Rozdzia(cid:293) 14. Testowanie, debugowanie i wyj(cid:233)tki Kup książkęPoleć książkę 14.11. Wy(cid:316)wietlanie komunikatów ostrzegawczych Problem Programista chce, aby program wy(cid:264)wietla(cid:228) komunikaty ostrzegawcze (np. o przestarza(cid:228)ych funkcjach lub problemach z dzia(cid:228)aniem). Rozwi(cid:233)zanie Aby wy(cid:264)wietla(cid:232) komunikaty ostrzegawcze w programie, nale(cid:276)y zastosowa(cid:232) funkcj(cid:246) warni (cid:180)ngs.warn(): import warnings def func(x, y, logfile=None, debug=False): if logfile is not None: warnings.warn( Argument logfile jest przestarza(cid:298)y , DeprecationWarning) ... Argumentami funkcji warn() s(cid:241) komunikat ostrzegawczy oraz klasa ostrze(cid:276)enia (zwykle jest to jedna z nast(cid:246)puj(cid:241)cych klas: UserWarning, DeprecationWarning, SyntaxWarning, RuntimeWarning, ResourceWarning lub FutureWarning). Obs(cid:228)uga ostrze(cid:276)e(cid:254) zale(cid:276)y od tego, w jaki sposób uruchomiono interpreter i skonfigurowano inne ustawienia. Je(cid:264)li uruchomisz Pythona z opcj(cid:241) –W all, uzyskasz dane wyj(cid:264)ciowe w na- st(cid:246)puj(cid:241)cej postaci: bash python3 -W all example.py example.py:5: DeprecationWarning: Argument logfile jest przestarza(cid:298)y warnings.warn( Argument logfile jest przestarza(cid:298)y
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Python. Receptury. Wydanie III
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: