9. Files

9.1. Path

9.1.1. Absolute path

  • Windows
    FILE = r'C:\Temp\iris.csv'
    
  • Linux, macOS, BSD

    FILE = r'/tmp/iris.csv'
    

9.1.2. Relative path

  • File in the same directory directory

    FILE = r'iris.csv'
    
  • File in parent directory

    FILE = r'../data/iris.csv'
    

9.2. Access modes

Character

Meaning

'r'

open for reading (default)

'w'

open for writing, truncating the file first

'a'

open for writing, appending to the end of the file if it exists

'rb'

read binary mode

'wb'

write binary mode

'ab'

append binary mode

9.3. Read from file

  • Works with both relative and absolute path

  • Uses context manager

9.3.1. Reading file line by line

  • Fails when directory with file cannot be accessed

  • Fails when file cannot be accessed

Listing 9.1. file can be iterated line by line
with open(r'/tmp/iris.csv') as file:
    for line in file:
        print(line)

9.3.2. Reading whole file content

Listing 9.2. Read whole file as a text to content variable
with open(r'/tmp/iris.csv') as file:
    content = file.read()

9.3.3. Reading file as list with lines

Listing 9.3. Convert file to list by line
with open(r'/tmp/iris.csv') as file:
    lines = file.readlines()

9.3.4. Read selected lines from file

Listing 9.4. Convert file to list by line, select 1-30 lines
with open(r'/tmp/iris.csv') as file:
    lines = file.readlines()[1:30]

9.4. Writing

9.4.1. Writing to file

  • Fails when directory with file cannot be accessed

  • Creates file if not exists

  • Overwrite old content

Listing 9.5. Writing to file
with open(r'/tmp/iris.csv', mode='w') as file:
    file.write('hello')

9.4.2. Appending to file

  • Fails when directory with file cannot be accessed

  • Creates file if not exists

  • Append to the end of file

Listing 9.6. Appending to file
with open(r'/tmp/iris.csv', mode='a') as file:
    file.write('hello')

9.5. Exception handling

Listing 9.7. Exception handling while accessing files
try:
    with open(r'/tmp/iris.csv') as file:
        content = file.read()
        print(content)

except FileNotFoundError:
    print('File does not exist')

except PermissionError:
    print('Permission denied')

9.6. Good Engineering Practises

  • FILE as a raw string r'...' constant

  • encoding='utf-8'

  • Use context manager

9.7. Assignments

9.7.1. Content of a requested file

  • Filename: file_content.py

  • Lines of code to write: 5 lines

  • Estimated time of completion: 5 min

  1. Napisz program, który wyświetli na ekranie zawartość pliku o nazwie podanej przez użytkownika.

  2. Dopisz obsługę wyjątków dla braku uprawnień oraz tego że plik nie istnieje.

9.7.2. Parsing simple CSV file

  1. Skopiuj plik do siebie na dysk i nazwij go iris.csv

  2. Dla każdej linii:

    1. Oczyść linię z białych znaków

    2. Podziel linię po przecinku

    3. Zapisz rekordy do:

      • X: List[Tuple[float]] - features

      • y: List[str] - labels

The whys and wherefores
  • czytanie i parsowanie pliku

  • nieregularne pliki konfiguracyjne (struktura może się zmieniać)

  • filtrowanie elementów

  • korzystanie z pętli i instrukcji warunkowych

  • parsowanie stringów

  • praca ze ścieżkami w systemie operacyjnym

9.7.3. Parsing /etc/hosts

  • Filename: file_hosts.py

  • Lines of code to write: 10 lines

  • Estimated time of completion: 20 min

  • Input data: Listing 9.8.

    Listing 9.8. Zawartość pliku hosts.txt
    ##
    # ``/etc/hosts`` structure:
    #   - IPv4 or IPv6
    #   - Hostnames
    ##
    
    127.0.0.1       localhost
    127.0.0.1       astromatt
    10.13.37.1      nasa.gov esa.int roscosmos.ru
    255.255.255.255 broadcasthost
    ::1             localhost
    
  1. Utwórz plik tekstowy hosts.txt

  2. Do pliku skopiuj kod z listingu Listing 9.8.

  3. Ważne, żeby przepisać zawartość zawierającą komentarze, białe spacje i linie przerwy

  4. Sparsuj plik i dla każdej linii:

    1. Pomiń linię jeżeli jest pusta, jest białym znakiem lub zaczyna się od komentarza

    2. Podziel linię po dowolnej ilości białych znaków (spacja, taby, itp)

    3. Wydziel ip i hosty

    4. Wykorzystaj jednolinikowego if do sprawdzenia czy jest kropka w adresie IP (to IPv4) w przeciwnym przypadku IPv6

    5. Do listy wynikowej dopisz słownik z ip, hostami i protokołem

    6. Jeżeli IP jest już wpisane do naszej listy wynikowej to scal listy hostname’ów dla wpisów o tym samym IP

  5. Na końcu przedstaw dane w formacie:

    • Wersja prosta Dict[str, dict]:

      {
          '127.0.0.1': {'protocol': 'ipv4', 'hostnames': ['localhost', 'astromatt']},
          '10.13.37.1': {'protocol': 'ipv4', 'hostnames': ['nasa.gov', 'esa.int', 'roscosmos.ru']},
          '255.255.255.255': {'protocol': 'ipv4', 'hostnames': ['broadcasthost']},
          '::1': {'protocol': 'ipv4', 'hostnames': ['localhost']},
      }
      
    • Wersja zaawansowana List[Dict[str, Union[str, List[str]]]:

      Listing 9.9. /etc/hosts example
      [
          {'ip': '127.0.0.1', 'protocol': 'ipv4', 'hostnames': ['localhost', 'astromatt']},
          {'ip': '10.13.37.1', 'protocol': 'ipv4', 'hostnames': ['nasa.gov', 'esa.int', 'roscosmos.ru']},
          {'ip': '255.255.255.255', 'protocol': 'ipv4', 'hostnames': ['broadcasthost']},
          {'ip': '::1', 'protocol': 'ipv6', 'hostnames': ['localhost']}
      ]
      
The whys and wherefores
  • czytanie i parsowanie pliku

  • nieregularne pliki konfiguracyjne (struktura może się zmieniać)

  • filtrowanie elementów

  • korzystanie z pętli i instrukcji warunkowych

  • parsowanie stringów

  • praca ze ścieżkami w systemie operacyjnym

Hints
  • str.isspace()

  • value = True if ... else False