Python Blocks

Първо малко преговор

  • Колекции
  • Какво е да те мързи?
  • Итератори
  • Генератори
  • Защо са толкова яки?
  • Малко допълнения

Errors

>>> print(This is a print message)
  File "<stdin>", line 1
    print(This is a print message)
                        ^
SyntaxError: invalid syntax
Най-често срещаните съобщения, които виждаме, докато учим Python, са Error messages.

При изпълнението на кода, Python parser-ът е открил грешка. Съобщава ни за нея чрез името й(SyntaxError) и стрелка къде е възникнала.
>>> for i in range(3):
...     print(2 * (2 / i))

Какво ще се изпълни?

>>> for i in range(3):
...     print(i)
...     print(2 * (2 / i))
... 
0
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
ZeroDivisionError: division by zero
Възникнала е грешка по време на изпълнение
Синтактично правилен код не ни гарантира, че програмата ни е валидна!
Errors(Грешки), хванати по време на изпълнение на кода, наричаме Exceptions(Изключения)!

Exceptions

>>> Roza + 'Roza'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Roza' is not defined

>>> magic_number = 41 + '1'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

>>> number = int("Some wild string")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'Some wild string'
  • Тип на грешката:
    Пример: TypeError, ValueError, ImportError, etc.

 

  • Описание на грешката:
    Пример: invalid literal for int() with base 10: 'Some wild string'

 

  • Къде е възникнала :
    Пример:  File "<stdin>", line 1, in <module>

Exception съобщението съдържа:

Как хващаме Exceptions?

Enter your age: 23
23
Enter your age: 44
44
Enter your age: ff
Traceback (most recent call last):
  File "handling_exceptions.py", line 7, in <module>
    age = int(input("Enter your age: "))
ValueError: invalid literal for int() with base 10: 'ff'
while True:
    age = int(input("Enter your age: "))
    print(age)

Как хващаме Exceptions?

Enter your age: 23
23
Enter your age: dd
Invalid number
Enter your age: 44
44
Enter your age: rozaaa
Invalid number
while True:
    try:
        age = int(input("Enter your age: "))
        print(age)
    except ValueError:
        print("Invalid number")

Как хващаме Exceptions?

Чрез Try/Except блок

try:
    pass # do something
except Exception:
    pass # catch one or more exceptions
else:
    pass # if try part is executed, execute and 'else' part of the block
finally:
    pass # part that executes after everything
try:
    f = open('text_file.txt')
except Exception as e:
    print('We hit an error: {}'.format(e))
else:
    print(f.read())
finally:
    if not f.closed:
        f.close()
В try клаузата се опитваме да отворим файл,

ако възникне каквато и да е грешка ще я хванем в except чрез класа Exception.

При успешно завършване на try, else частта ще бъде изпълнена. Finally се изпълнява винаги!

 

  • можем да хванем конкретна грешка

 

 

  • ако не знаем какви грешки могат да възникнат, съществува generic class Exception, който да извикаме

В except клаузата

try:
    f = open('some_file.txt')
except FileNotFoundError:
    print('''We hit an error! 
             This file does not exist!''')
try:
    file_name = input('Enter a file name: ')
    f = open(file_name)
    f.write(10 / 0)
except Exception as e:
    print('''Sorry, something went wrong! 
             You hit an error: {0}'''.format(e))
try:
    f = open('roza_custom_file')
    Roza = StrangeObject
except (FileNotFoundError, NameError) as e:
    print('Something went wrong')
try:
    file_name = input('Enter a file name: ')
    f = open(file_name)
    var = variable
except FileNotFoundError:
    print('We hit an error! This file does not exist!')
except NameError as e:
    print('You hit an error: {0}'.format(e))
Можем да хванем повече от една грешка
Ако искаме едно и също съобщение да се връща от няколко грешки, ги обединяваме!

Можем да създадем 'наши' (custom) Exception

# define custom exceptions
class Error(Exception):
   """Base class for other exceptions"""
   pass

class InvalidUsernameError(Error):
   """Raised when the username is invalid"""
   pass

# our main program


while True:
   try:
       username = input("Username: "))
       if not is_valid(username):
           raise InvalidUsernameError
       break
   except InvalidUsernameError:
       print("Invalid username!")

Какво е това?

with open('some_file.txt', 'r+') as fn:
    data = fn.read()
    print(data)
    i = 0
    while i < 10:
        file_new_data = input('Enter information: ')
        fn.write(file_new_data)
        i += 1

With Statement Context Managers

Какво е With Statement Context Managers?

Обект, който дефинира контекста в with блока, по време на изпълнение на кода

Какъв проблем решават?

# set things up
try:
    # do something
    pass
finally:
    # tear things down
    pass

Структура на Context Manager

class some_context_manager:
    def __enter__(self):
        # set things up
        pass

    def __exit__(self, type, value, traceback):
        # tear things down
        pass

with some_context_manager() as thing:
     # some code
     pass
__enter__(self) и __exit__(self) наричаме Guardians на Context Manager-a

Пример

class Log:
    def __init__(self, filename):
        self.filename = filename
        self.file_handler = None

    def logging(self, text):
        self.file_handler.write(text + '\n')

    def __enter__(self):
        print("__enter__")
        self.file_handler = open(self.filename, "r+")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")
        self.file_handler.close()
        return True

Начини на използване

with Log("log_file.txt") as logfile:
    print("In with block")
    logfile.logging("Test1 for logfile")
    logfile.logging("Test2 for logfile")


# Result 
# __enter__
# In with block
# __exit__
with Log("log_file1.txt") as l1:
    l1.logging("In file 1")
    var = 5
    with Log("log_file2.txt") as l2:
        l2.logging("Logginf in file 2: {0}".format(var))
Съществува и nested with block
with Log("log_file1.txt") as l1, Log("log_file2.txt") as l2:
    l1.logging("In file 1")
    var = 5
    l2.logging("Logginf in file 2: {0}".format(var))

Но ние сме мързели, нали?

Понякога да пишем класове е досадно => : (

Затова в Python съществува contexlib библиотека => : )

from contextlib import contextmanager

@contextmanager
def working_with_file(filename):
    fn = open(filename)
    yield fn
    fn.close()

with working_with_file('some_file.txt') as f:
    print(f.read())
Чрез декоратор от библиотеката можем да създадем Context Manager!
from contextlib import contextmanager

@contextmanager
def make_context():
    print('entering')
    try:
        yield "Yielding......."
    except RuntimeError as err:
        print('ERROR: {0}'.format(err))
    finally:
        print('exiting')

with make_context() as value:
    print('inside with statement: {}'.format(value))

Try/Except Blocks

By Hack Bulgaria

Try/Except Blocks

  • 1,431