11. Files

11.1. Path

11.1.1. Absolute path

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

    FILE = r'/tmp/iris.csv'
    

11.1.2. Relative path

  • File in the same directory directory

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

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

11.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

11.3. Read from file

  • Works with both relative and absolute path
  • Uses context manager

11.3.1. Reading file line by line

  • Fails when directory with file cannot be accessed
  • Fails when file cannot be accessed
Code Listing 11.1. file can be iterated line by line
with open(r'/tmp/iris.csv') as file:
    for line in file:
        print(line)

11.3.2. Reading whole file content

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

11.3.3. Reading file as list with lines

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

11.3.4. Read selected lines from file

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

11.4. Writing

11.4.1. Writing to file

  • Fails when directory with file cannot be accessed
  • Creates file if not exists
  • Overwrite old content
Code Listing 11.5. Writing to file
with open(r'/tmp/iris.csv', mode='w') as file:
    file.write('hello')

11.4.2. Appending to file

  • Fails when directory with file cannot be accessed
  • Creates file if not exists
  • Append to the end of file
Code Listing 11.6. Appending to file
with open(r'/tmp/iris.csv', mode='a') as file:
    file.write('hello')

11.5. Exception handling

Code Listing 11.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')

11.6. Good Engineering Practises

  • FILE as a raw string r'...' constant
  • encoding='utf-8'
  • Use context manager

11.7. Assignments

11.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.

11.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

11.7.3. Parsing /etc/hosts

  • Filename: file_hosts.py

  • Lines of code to write: 10 lines

  • Estimated time of completion: 20 min

  • Input data: Code Listing 11.8.

    Code Listing 11.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 Code Listing 11.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]]]:

      Code Listing 11.9. /etc/hosts example
      [
          {'hostnames': ['localhost'], 'ip': '127.0.0.1', 'protocol': 'ipv4'},
          {'hostnames': ['astromatt'], 'ip': '127.0.0.1', 'protocol': 'ipv4'},
          {'hostnames': ['nasa.gov', 'esa.int', 'roscosmos.ru'], 'ip': '10.13.37.1', 'protocol': 'ipv4'},
          {'hostnames': ['broadcasthost'], 'ip': '255.255.255.255', 'protocol': 'ipv4'},
          {'hostnames': ['localhost'], 'ip': '::1', 'protocol': 'ipv6'}
      ]
      
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