CodeGym /Kursy /Python SELF PL /Operator with

Operator with

Python SELF PL
Poziom 21 , Lekcja 3
Dostępny

4.1 Zamknięcie pliku i obsługa błędów

Czasem podczas czytania pliku występują błędy lub wyjątki i plik zostaje niezamknięty. To może prowadzić do wycieku pamięci lub wycieku file handler’ów. Dlatego pracę z plikiem warto opakować w blok try-except.

Załóżmy, że miałeś taki kod:


file = open('example.txt', 'a') # Otwieramy plik
file.write("This is a new line added to the file.")
file.close()  # Zamykamy plik

Trzeba go opakować w blok try-except:


try:
    file = open('example.txt', 'a')  # Otwieramy plik
    file.write("This is a new line added to the file.")
    file.close()  # Zamykamy plik
except FileNotFoundError:
    print("File not found")
    file.close()  # Zamykamy plik

Aby nie pisać metody close() dwa razy, można ją przenieść do bloku finally:


try:
    file = open('example.txt', 'a')  # Otwieramy plik
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # Zamykamy plik

Ten kod wygląda schludnie, ale… nie działa, ponieważ zmienna file jest zdefiniowana tylko w bloku try i nie jest dostępna z bloków except i finally.

W związku z tym musimy zdefiniować zmienną na wyższym poziomie:


file = None
try:
    file = open('example.txt', 'a')  # Otwieramy plik
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    file.close()  # Zamykamy plik

To rozwiązanie jest lepsze, ale ma swoje wady. Na przykład, jeśli plik nie zostanie otwarty, to w zmiennej file pozostanie None. I wtedy próba zamknięcia pliku wywoła błąd — będzie próba wywołania metody close() dla nieistniejącego obiektu.

W związku z tym musimy dodać sprawdzenie przed wywołaniem metody close():


file = None
try:
    file = open('example.txt', 'a')  # Otwieramy plik
    file.write("This is a new line added to the file.")
except FileNotFoundError:
    print("File not found")
finally:
    if file:
        file.close()  # Zamykamy plik

Jeśli jesteś zdziwiony, że 3 linijki kodu zamieniły się w 9, to nie jesteś sam. Na szczęście już jest gotowe rozwiązanie tego problemu, o którym powiemy dalej.

4.2 Operator with

Operator with w Pythonie daje wygodny sposób zarządzania zasobami, takimi jak pliki, zapewniając ich automatyczne zamykanie po zakończeniu bloku with. To upraszcza kod i zapobiega wyciekom zasobów, takich jak niezapisane pliki.

Ogólna składnia operatora with:


with wyrażenie as zmienna:
    praca z zmienną

Operator with służy do opakowywania wykonania bloku kodu menedżerem kontekstu. Przy użyciu operatora with Python automatycznie wywołuje metody __enter__() i __exit__() obiektu menedżera kontekstu, co upraszcza zarządzanie zasobami.

Przykład użycia with do pracy z plikami:


with open('example.txt', 'w') as file:
    file.write("Hello, World!\n")
    file.write("This is a test file.\n")

W tym przykładzie plik example.txt jest otwierany w trybie zapisu, a nazwa pliku jest przypisywana do zmiennej file. Blok kodu wewnątrz with automatycznie zamyka plik po wykonaniu wszystkich operacji zapisu.

4.3 Automatyczne zamknięcie pliku

Jednym z głównych zalet użycia operatora with jest automatyczne zamknięcie pliku po zakończeniu bloku kodu. To się dzieje nawet w przypadku wystąpienia wyjątku, co czyni kod bardziej bezpiecznym i niezawodnym.

Przykład automatycznego zamknięcia pliku:


try:
    with open('example.txt', 'w') as file:
        file.write("Hello, World!\n")
        file.write("This is a test file.\n")
        # Wyjątek, aby sprawdzić, czy plik i tak się zamknie
        raise Exception("Something went wrong")
except Exception as e:
    print(f"Caught an exception: {e}")
# W tym momencie plik jest już zamknięty

Zawsze używaj operatora with przy pracy z plikami. To proste i pozwala uniknąć wielu błędów.

4.4 Pod maską operatora with

Podstawą działania operatora with są metody __enter__() i __exit__(), które muszą być zrealizowane w klasie, używanej jako menedżer kontekstu.

Aby obiekt mógł być używany z operatorem with, musi realizować metody __enter__() i __exit__(). Te metody definiują zachowanie przy wejściu i wyjściu z kontekstu.

Metoda __enter__()

Metoda __enter__() jest wywoływana przy wejściu do bloku with. Wykonuje inicjalizację zasobu i zwraca obiekt, który będzie powiązany ze zmienną, określoną po as.

Metoda __exit__()

Metoda __exit__() jest wywoływana przy wyjściu z bloku with. Wykonuje działania końcowe, takie jak zwolnienie zasobów lub zamknięcie plików. Metoda przyjmuje trzy argumenty: exc_type, exc_val i exc_tb, które zawierają informacje o wyjątku, jeśli wystąpił.

  • exc_type: typ wyjątku (na przykład ZeroDivisionError).
  • exc_val: wartość wyjątku (na przykład komunikat o błędzie).
  • exc_tb: ślad stosu wyjątku.

Jeśli metoda __exit__() zwraca True, to wyjątek zostanie zignorowany. Jeśli zwraca False, wyjątek zostanie ponownie wzbudzony.

Przykład:


class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print(f"An exception occurred: {exc_type}, {exc_val}")
        return False  # Wyjątek nie jest pomijany
        
with MyContextManager() as manager:
    print("Inside the with block")
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION