PPy3/WejścieWyjście
Spis treści
Obsługa wejścia i wyjścia
Większość sensownych programów służy do przetworzenia jakichś informacji uzyskanych z zewnątrz programu: w najprostszym przypadku, z pliku na dysku, lub z danych wprowadzonych przez użytkownika za pomocą klawiatury. W przypadku programów wywoływanych z linii poleceń, istnieje też poręczny i łatwy do wykorzystania mechanizm by wskazać programowi, co ma robić - za pomocą tzw. opcji i/lub wartości parametrów wpisanych na linii poleceń, po nazwie wywoływanego programu. Często też chcemy, by wyniki działania programu, np. przetworzone dane lub wyniki obliczeń, znalazły się w pliku na dysku - choć czasami możemy woleć, aby również (lub zamiast tego) zostały one wyświetlone na ekranie. Omówimy teraz krótko, jak to osiągnąć.
Pliki tekstowe vs. binarne
Zawartość każdego pliku na dysku to tak naprawdę strumień bajtów - bajt, czyli grupa ośmiu bitów, może być traktowany jako reprezentacja (w zapisie dwójkowym), jakiejś liczby całkowitej dodatniej z zakresu 0-255. Często jednak zawartość ta ma być traktowana jako reprezentacja tekstu, czyli ciągu znaków stosowanych w zapisie jakiegoś języka - może to być język naturalny (polski, angielski, chiński, ...) lub np. język programowania (Python, Java, C++, ...), język tworzenia stron WWW (HTML), itd. W tym celu stworzono tzw. kodowania, czyli standardy reprezentowania znaków stosowanych w systemach zapisu języków naturalnych za pomocą bajtów lub grup bajtów (języki programowania itp. zasadniczo posługują się tymi samymi zestawami znaków, co języki naturalne - a zwłaszcza angielski).
Nie wchodząc za bardzo w szczegóły, obecnie stosowane reprezentacje cyfrowe tekstu oparte są na standardzie Unicode, który m. in. definiuje tzw. uniwersalny zestaw znaków (UCS) - tablicę, zawierającą wszystkie znaki (alfanumeryczne, przestankowe, ideogramy - właściwe dla języków dalekowschodnich, i szeregu innych kategorii) stosowane w systemach pisma wszystkich żywych języków świata (i wielu języków martwych). Wewnętrzna reprezentacja danych napisowych w Pythonie oparta jest na standardzie Unicode - zatem pythonowy napis może zawierać znaki z wszelkiego rodzaju systemów pisma, w dowolnej kombinacji. Zapis tych danych w pliku dyskowym - i odwrotne, zinterpretowanie strumienia bajtów odczytanego z pliku dyskowego jako reprezentacji pewnego napisu - wymaga przyjęcia jakiegoś konkretnego kodowania. Unicode nie stanowi sam w sobie kodowania - określa on repertuar znaków oraz pozycję każdego z nich w tablicy UCS, nie zaś bajt lub grupę bajtów go reprezentującą.
W Pythonie problem ten rozwiązany jest w sposób następujący: domyślnie, zawartość wczytywana z plików interpretowana jest jako dane tekstowe (chyba, że zażyczymy sobie inaczej), zgodnie z pewnym domyślnym kodowaniem, właściwym dla systemu operacyjnego (chyba, że wskażemy że ma być stosowane inne) - w przypadku Linuxa będzie to prawie zawsze kodowanie o nazwie UTF-8, które się dobrze nadaje do zastosowania dla języków zachodnich, posługujących się systemem pisma opartym na alfabecie łacińskim. Inaczej może być w środowiskach języków posługujących się np. cyrylicą, czy języków azjatyckich (pismo arabskie lub ideograficzne - chińskie, japońskie, koreańskie, itd.). W środowiskach Windows może być inaczej...
Z powyższego widać, że rozróżnienie - plik tekstowy czy binarny - jest dość umowne, i dotyczy raczej interpretacji zawartości pliku (plik zapisany zgodnie z nieznanym nam i/lub nieoczekiwanym kodowaniem jest nie do odróżnienia od pliku binarnego). Co więcej, pliki zapisywane przez programy takie, jak MS Word, lub pliki PDF, nawet zawierające wyłącznie tekst, nie są w tym rozumieniu plikami tekstowymi, tylko binarnymi. W przykładach będziemy mieli do czynienia prawie wyłącznie z plikami tekstowymi - warto jednak wiedzieć, że w Pythonie jest osobny typ danych - ciągi bajtów (bytes), o własnościach nieco podobnych do napisów, ale o elementach będących bajtami, a nie znakami pisma.