Zaawansowane Metody Geoinformatyczne

Adam Inglot
Adiunkt w Katedrze Geodezji
Wydział Inżynierii Lądowej i Środowiska, Politechnika Gdańska
adam.inglot@pg.edu.pl

2022-10-11, aktualizacja 2022-10-17

© ainglot.pl, 2022. Udostępnianie i wykorzystanie zgodnie z licencją Creative Commons Attribution 4.0 International license (CC BY 4.0).
Projekt strony zapożyczony za zgodą autora - Paulo Raposo

CC By 4.0

Podstawy pracy w Python

W drugiej części wprowadzenia do Pythona zapoznamy się z definiowaniem własnej funkcji, trzema modułami z podstawowych bibliotek Pythona: os, datetime i random. Przyglądniemy się też podstawowemu sposobowi obsługiwania plików, na przykładzie i zastosowaniu do pliku tekstowego.

Definiowanie własnej funkcji def

Budując własną funkcję w języku Python możemy utworzyć jedną z czterech rodzajów funkcji: globalną, lokalną, lambda lub metodę. My na potrzeby kursu ograniczymy się do używania, tworzenia funkcji globalnych. Ogólna składnia funkcji def:

1def nazwa_funkcji(pierwszyParametr...):
2pakiet

Parametry które możemy podać są opcjonalne, możemy je podać jako sekwencję identyfikatorów oddzielonych przecinkami lub jako sekwencja par identyfikator=wartość. Podczas użycia funkcji należy wprowadzić dokładnie tyle parametrów ile jest wymaganych (podanych w nawiasie okrągłym), w przeciwnym razie zwrócony zostanie błąd w wyniku działania funkcji. Sprawdźmy na przykładzie jak zastosować funkcję def:

1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr):
2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr
3return sumaParametrow
4
5print(suma_trzech_parametrow(1, 2, 3)

Wynik działania skryptu:

Run:
6
Process finished

W powyższym przykładzie zostały zastosowane argumenty pozycyjne, czyli wykonując funkcję podajemy na konkretnej pozycji wartość jaką ma przyjmować dany parametr. Możemy argument pozycyjny zamienić na argument z wartością domyślną, wtedy nie musimy podawać argumenty a funkcja zostanie wykonana z wprowadzoną wartością domyślną.

1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr=3):
2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr
3return sumaParametrow
4
5print(suma_trzech_parametrow(1, 2)

Wynik działania skryptu z wartością domyślną:

Run:
6
Process finished

Przy zastosowaniu wartości domyślnej możemy pozostawić tę wartość jak w kodzie powyżej lub wprowadzić na ostatnią pozycję wartość dla której chcemy przeprowadzić działanie:

1def suma_trzech_parametrow(pierwszyParametr, drugiParametr, trzeciParametr=3):
2sumaParametrow = pierwszyParametr + drugiParametr + trzeciParametr
3return sumaParametrow
4
5print(suma_trzech_parametrow(1, 2, 10)

Wynik działania skryptu gdzie wartość domyślna została zastąpiona:

Run:
13
Process finished

Podczas projektowania własnej funkcji z wartością domyślną, należy pamiętać że w pierwszej kolejności należy wprowadzić argumenty pozycyjne a po nich, argumenty z wartością domyślną.

Moduł os

Do czego może nam się przydać moduł os? Najprościej można odpowiedzieć że na potrzeby dostępu do plików i folderów. Dzięki metodom z tego modułu możemy np. wylistować pliki i foldery z podanej lokalizacji, usunąć lub skopiować plik, wyodrębnić nazwę pliku czy rozszerzenia.

Dla podanych metod sposób importu biblioteki os wygląda w taki sposób: import os.

składniaopis
os.listdir(path)zwraca w formie listy zawartość podanego folderu
os.remove(file)usuwa plik z podanej lokalizacji
os.rename(oldFile, newFile)zmienia nazwę pliku, podajemy dwa argumenty, pierwszy to istniejący plik z ścieżką, drugi nowa nazwa pliku z miejscem docelowym
os.replace(oldFile, newFile)zmienia miejsce i nazwę pliku
os.path.abspath(path)metoda ta podaje pełną ścieżkę do pliku
os.path.dirname(file)wydziela samą ścieżkę
os.path.exists(file)zwraca wartość True w przypadku gdy plik istnieje
os.path.getatime(file)zwraca datę i czas w formie liczby typu float założenia pliku
os.path.getmtime(file)zwraca datę i czas w formie liczby typu float modyfikacji pliku
os.path.getsize(file)zwraca rozmiar pliku mierzony w bajtach
os.path.join(path, name.r)łączy ścieżki lub ścieżkę i nazwę pliku
os.path.split(path)dzieli ścieżkę na dwie części i zapisuje do krotki, dzieli ścieżkę na ostatni składnik i resztę, jeżeli mamy ścieżkę do pliku to podzieli nam na ścieżkę i nazwę pliku z rozszerzeniem
os.path.splitext(name.r)rozdziela nazwę pliku z rozszerzeniem w postaci krotki gdzie mamy wydzieloną nazwę i rozszerzenie

Dokumentacja modułu os jest dostępna na stronach internetowych python.org moduł os.

Przykłady zastosowania moduły os

Na potrzeby przykładu posłużymy się folderem który zawiera kilka plików:

image

Wyświetlmy jakie pliki zawiera podany folder:

image

Można użyć pętli for do bardziej czytelnej formy prezentacji listy plików:

image

Sprawdźmy parametry plików takie jak, czas założenia pliku i rozmiar:

image

Format czasu podany w tej formie, jest niejasny dla człowieka, nie jesteśmy w stanie określić roku, dnia czy godziny. W kolejnym module poznamy metody dzięki którym będziemy w stanie zamienić liczbę na datę i czas.

Moduł datetime

Dla podanych metod sposób importu biblioteki datetime wygląda w taki sposób: import datetime as dt.

składniaopis
dt.datetime.now()wywołanie aktualnej daty i czasu z dokładnością do 6 miejsc po przecinku dal sekund, w lokalnej strefie czasowej
dt.timedelta.total_seconds()
dt.datetime.utcnow()wywołanie aktualnej daty i czasu z dokładnością do 6 miejsc po przecinku dal sekund, dla strefy 0 UTC
dt.datetime(y, m, d, H=0, M=0, S=0, MS=0, tzinfo=None, *, fold=0)konwertuje podane wartości na obiekt datetime, wymaga minimum trzech argumentów, y=rok, m=miesiąc, d=dzień
t.isoformat()konwertuje obiekt datetime na typ string w formacie iso, np. '2022-10-15T14:31:53'
dt.datetime.fromisoformat(datetime_iso_string)konwertuje date i czas zapisany w formacie iso na obiekt datetime, np. '2022-10-15T14:31:53'
t.strftime(format)konwertuje obiekt datetime do string używając kombinacji parametrów z tabeli poniżej
dt.datetime.fromtimestamp(datetime_float)konwertuje liczbę zmiennoprzecinkową na obiekt datetime

Kolejna tabela przedstawia oznaczenia formatu konwersji daty i czasu z obiektu datetime do string. Dzięki tym parametrom jesteśmy w stanie skomponować formę zapisu daty i czasu do ciąg znaków w dowolnej kombinacji.

oznaczenieznaczenieprzykład, wynik
`%y`zwraca dwucyfrową liczbę reprezentującą rok w obrębie jednego wieku01, 02, ..., 99
`%Y`zwraca czterocyfrową liczbę reprezentującą rok0001, 0002, ..., 2022, 2023, ..., 9998, 9999
`%m`zwraca dwucyfrową liczbę reprezentującą miesiąc01, 02, ..., 12
`%b`zwraca trzy literowy ciąg znaków reprezentującą miesiącJan, Feb, ..., Dec (en_US);
`%B`zwraca pełną nazwę miesiącaJanuary, February, ..., December (en_US);
`%d`zwraca dwucyfrową liczbę reprezentującą dzień w obrębie miesiąca01, 02, ..., 31
`%H`zwraca dwucyfrową liczbę reprezentującą godzinę do 24h01, 02, ..., 24
`%I`zwraca dwucyfrową liczbę reprezentującą godzinę do 12h01, 02, ..., 12
`%p`oznaczenie pory dnia, przed południem czy popołudniuAM, PM (en_US);
`%M`zwraca dwucyfrową liczbę reprezentującą minuty00, 01, 02, ..., 59
`%S`zwraca dwucyfrową liczbę reprezentującą sekundy00, 01, 02, ..., 59
`%f`zwraca sześciocyfrową liczbę reprezentującą mikrosekundy00, 01, 02, ..., 59
`%j`zwraca trzycyfrową liczbę reprezentującą dzień liczony od początku roku001, 002, 003, ..., 366

Obie tabele zostały przygotowane na podstawie dokumentacji przedstawionej na stronie python.org moduł datetime.

Przykłady zastosowania modułu datetime

Zacznijmy od niedokończonego zadania z modułu os, odczytaliśmy informację o założeniu pliku ale w formie liczby, która jest trudna przez człowieka do interpretacji. Zamieńmy te liczby na czas w konwencjonalnej formie. Użyjemy do tego na początek metody fromtimestamp.

image

Uwzględniając lokalny czas, za pomocą metody dt.timezone.utc

image

Moduł random

składniaopis
random.randint(a, b)zwraca liczbę całkowitą n z zakresu a ≤ n ≤ b, podobną metodą jest random.randrange()
random.choice(sekwencja)zwraca jeden element z wskazanej sekwencji, sekwencją może być lista, krotka czy też ciąg znaków
random.random()zwraca liczbę zmiennoprzecinkową z zakresu [0.0, 1.0)
random.uniform(a, b)zwraca liczbę zmiennoprzecinkową n z zakresu a ≤ n ≤ b
random.sample(listValues, counts=countValue, k=countSample)zwraca listę wartości wybranych z listValues, parametr countValue odpowiada liczebnością liście listValues i służy do zwielokrotnienia występowania danej wartości na tych samych pozycjach, parametrcountSample to liczba naturalna określająca ile ma się znajdować wartości w liście wynikowej, przy czym countSample ≤ len(listValues) lub kombinacji list listValues i countValue

Przykłady zastosowania moduły random

Moduł generujący liczby pseudolosowe głównie może nam się przydać do wprowadzenia danych testowych, sztucznie wygenerowanych współrzędnych lub z puli danych przygotować część losowo wybranych obiektów.

Przyglądnijmy się jak wygenerować listę 30 liczb całkowitych w przedziale (100, 200) - nie uwzględniając liczb 100 i 200:

1import random
2listaDanych = []
3for i in range(30):
4listaDanych.append(random.randint(101, 199))

Sprawdź wynik działania skryptu w Python.

image

Teraz sprawdźmy czy w naszej liście są takie liczby które występują więcej niż 1 raz, skorzystajmy z metody count którą możemy zliczyć wystąpienia w liście:

image

W takim razie zastosujmy metodę sample do wygenerowania liczb unikalnych w obrębie zakresu danych, możemy to wykonać podając zakres wartości z jakiego ma metoda pobierać wartości:

image

Po sprawdzeniu czy występują jakieś powielone liczby z podanego zakresu, program nie wykazuje nam żadnych powieleń.

Obsługa pliku tekstowego

Zapis i odczyt pliku tekstowego jest stosunkowo prostą operacją, komplikuje się w momencie pozyskiwania informacji z ciągu znaków. Inaczej mówiąc, gdy projektujemy sposób zapisu danych do liku tekstowego, musimy tak przygotować, zaprogramować zapis danych aby w łatwy sposób te dane ponownie wprowadzić do pierwotnej formy. Co może stanowić problem. Rozważmy zapis współrzędnych do pliku tekstowego, wiemy że część całkowita od części dziesiętnej jest separowana kropką ., jeżeli jako separator wybierzemy kropkę a nie przecinek czy średnik, to przy odczytywaniu danych będziemy mieli więcej pracy.

Odczytywanie pliku tekstowego jest obsługiwane przez metodę open, natomiast czytanie linii po linii w pliku tekstowym wykonuje się za pomocą pętli for z metodą file.readlines(). Zapisywanie danych do pliku tekstowego również odbywa się z wykorzystaniem metodę open a poszczególne elementy wprowadzamy za pomocą metody file.write(<i>tekst</i>). Zobaczmy ogólną składnie z dodatkowymi elementami:

Odczytywanie informacji zawartych z pliku txt:

1inFile = open('NameFile.txt', "r", encoding="utf8")
2for line in inFile.readlines():
3line.split("")
4...
5inFile.colse()

Zapisywanie danych do pliku txt:

1outFile = open('NameFile.txt', "w", encoding="utf8")
2outFile.write(tekst)
3outFile.colse()

Przykłady zastosowania odczytu plików txt

Pobierzmy dane badawcze udostępnione na portalu Most Danych, dane te udostępnione są w formie pliku txt zawierającym współrzędne przestrzenne (x, y, z) w lokalnym systemie współrzędnych. Odczytajmy te dane za pomocą powyższych składni, obliczmy ile jest punktów w pliku.

1inFile = open(r"D:\GIS\Dane\silo.txt", "r", encoding="utf8")
2sumLine = 0
3for xyz in inFile.readlines():
4sumLine += 1
5print(sumLine)

Wynik działania skryptu:

Run:
447693
Process finished

Zmodyfikujmy plik w taki sposób żeby w pierwszej linijce podana była informacja o nazwie kolumn: x y z

1inFile = open(r"D:\GIS\Dane\silo.txt", "r", encoding="utf8")
2outFile = open(r"D:\GIS\Dane\new_silo.txt", "w", encoding="utf8")
3
4newText = 'x y z \n'
5for xyz in inFile.readlines():
6newText += xyz
7
8outFile.write(newText)

image

[1] Mark Summerfield, Python 3 - kompletne wprowadzenie do programowania. Helion, wydanie 2, ISBN: 978-83-246-2642-7, 2010.
[2] Dokumentacja Python. https://docs.python.org/3/, (data dostępu 10.10.2022).