Основне меню  

   

Реклама  

Скачуйте відеуроки для створення сайту за допомогою SMS Joomla 

реклама

 

 

   

Ми в Facebook  

Калькулятор расчета пеноблоков смотрите на этом ресурсе
Все о каркасном доме можно найти здесь http://stroidom-shop.ru
Как снять комнату в коммунальной квартире смотрите тут comintour.net
   

Реклама в мережі  

   

Статистика  

Користувачі
1
Статті
180
Перегляди статей
595310
   

Пошук по сайту  

   

Ми знаходимось тут  

   

Випадкове фото  

   

Наш відеоканал  

   

Відвідування сайту  

Яндекс.Метрика

 

   

Посібник Delphi  

ДОСТУПНИЙ ВИКЛАД,

ЦІКАВІ ПРИКЛАДИ, ВИХІДНІ КОДИ.

ЦІНА ДИСКА З МАТЕРІАЛАМИ - 500 грн. 

Якщо ваша карта обслуговується ПриватБанком тоді переведіть потрібну суму через Приват24 на карту    5168 7573 0556 9925 або натисніть на посилання "Перейти до оплати", щоб здійснити миттєвий платіж без комісії. Перейти до оплати!

 Звертайтесь за адресою еmail:kuzbyt@ukr.net

 
   

Відеокурс по С++  

   

Рекомендуємо:  

   

Ми в контактах  

   

Сайти  

Українські уроки про ІТ

Єдина Країна! Единая Страна!

 

Українські уроки про програмування

 

 
   

Вступ

Якщо ви їх ще не зустрічали, тоді ви просто ще недостатньо старалися! Хто вони? Помилки. Проблеми. Баги. Винятки. Жуки. Розумієте про що я? Я зрозумів про що це з оцієї програми:

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# -*- coding: utf-8 -*-

# функція меню

def menu(list, question):

    for entry in list:

        print 1 + list.index(entry),

        print ") " + entry

 

    return raw_input(question) - 1

 

# визначаэмо наш список опцій для меню

options = ['A','B','C','D','E','F','H','I']

 

# викликаємо нашу функцію

answer = menu(options, 'Яка ваша улюблена літера? ')

 

print 'Ваша відповідь ' + (options[answer])

Це приклад програми меню, яку ми, якщо пам’ятаєте, писали в одному із попередніх уроків. На перший погляд програма виглядає просто чудово! Принаймні до моменту, допоки ми з вами пробуємо її вперше запустити. Ану давайте запустіть її. Що отримали?

Жуки (Bugs, Баги) – Людські Помилки

Найбільш часті проблеми з вашим кодом будуть ті, які ви самі ж зробите  Сумно, але правда. Отже, запустивши вище наведений приклад коду ми з вами отримаємо наступний вивід:

 

1

2

3

4

5

6

Traceback (most recent call last):

  File "test.py", line 14, in <module>

    answer = menu(options, 'Яка ваша улюблена літера? ')

  File "test.py", line 8, in menu

    return raw_input(question) - 1

TypeError: unsupported operand type(s) for -: 'str' and 'int'

Знаєте що? Python намагається сказати в чому причина поломки нашої програми. Він дає нам знати, що ми не можемо віднімати число від стрічки. Давайте ще раз глянемо на помилку (трейсбек, traceback – так називається повний вивід помилки):

·         “File “test.py”, line 14, in <module>” - пояснює нам кілька речей: в якому файлі (модулі) виникла помилка, та у якій саме стрічці (рядочку) цього файла. Ця інформація є дуже корисною, особливо якщо ми працюємо одночасно над великою кількістю модулів та Пітон коду. Слово <module> каже нам, що помилка сталася на кореневому рівні нашого модуля (а не в всередині функції чи класу)

·         “answer = menu(options, ‘Яка ваша улюблена літера? ‘)” – далі бачимо цю стрічку, яка показує якраз стрічку номер 14 у нашому файлі. У даній стрічці бачимо виклик нашої функції menu, саме тому наступна стрічка трейсбеку заходить в дану функцію і ще більше деталізує нам причину поломки:

·         “File “test.py”, line 8, in menu” – всередині функції ‘menu’ в рядочку 8 нашого модуля маємо наступний код:

·         “return raw_input(question) – 1″ – який і є причиною нашої помилки. Очевидно функція raw_input повертає дані типу стрічка, і не конвертує введений користувачем номер меню в число, а передає його як стрічку. Тому операція віднімання одинички від стрічки закінчується поломкою:

·         “TypeError: unsupported operand type(s) for -: ‘str’ and ‘int’” – останній рядочок трейсбеку є найбільш важливим і розказує нам конкретно про тип помилки та дає нам її деталі. У нашому випадку ми маємо ‘TypeError’, що означає нестиковку різних типів даних – стрічки та числа. Тобто Пітон не може відняти об’єкт типу типу ‘int’ від об’єкта типу ‘str’.

Наша програма є досить проста, тому трейсбек є простим та коротким, вказуючи лише на два рядочки у нашому файлі. Ті рядочки, які спричинили помилку. Зазвичай у реальних аплікаціях трейсбек буває довгим, і для того, щоб прослідкувати весь ланцюжок подій і докопатися до справжньої причини помилки часто приходиться прогулюватися по десятках рядочків коду та різних Пітон модулях, що задіяні у її трейсбеку.

Ось приклад такого складнішого трейсбеку (це моя помилка при розробці під платформу Plone CMS):

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Traceback (innermost last):

Module ZPublisher.Publish, line 115, in publish

Module ZPublisher.mapply, line 88, in mapply

Module ZPublisher.Publish, line 41, in call_object

Module Products.CMFPlone.FactoryTool, line 361, in __call__

Module Products.CMFPlone.FactoryTool, line 147, in __getitem__

Module Products.CMFPlone.PloneFolder, line 406, in invokeFactory

Module Products.CMFCore.TypesTool, line 934, in constructContent

Module Products.CMFCore.TypesTool, line 345, in constructInstance

Module Products.CMFCore.TypesTool, line 357, in _finishConstruction

Module Products.CMFCore.CMFCatalogAware, line 145, in notifyWorkflowCreated

Module Products.CMFCore.WorkflowTool, line 355, in notifyCreated

Module Products.DCWorkflow.DCWorkflow, line 392, in notifyCreated

Module Products.DCWorkflow.DCWorkflow, line 476, in _changeStateOf

Module Products.DCWorkflow.DCWorkflow, line 571, in _executeTransition

Module Products.DCWorkflow.DCWorkflow, line 435, in updateRoleMappingsFor

Module Products.DCWorkflow.utils, line 60, in modifyRolesForPermission

Module AccessControl.Permission, line 93, in setRoles

AttributeError: appname

Розбирати вище наведений приклад не будемо, адже він досить складний. Навів його, щоб ви лише побачили на скільки великим можемо бути справжній трейсбек помилки.

Значить вертаємося до нашої попередньої помилки. Ми вже знаємо її причину, так? Адже на рядочку 8-му нашої програми ми пробуємо відняти число від стрічки:

 

1

    return raw_input(question) - 1

Функція ‘raw_input’ завжди повертає стрічку, тому у нас є проблемка. Давайте змінимо її на функцію ‘input’. Дана функція не лише отримує та повертає у нашу програму дані введені користувачем, але вона ще й пробує вгадати та конвертувати їх до типу даних існуючих в Пітоні. Тобто, якщо користувач ввів число ’5′, тоді вона поверне в програму нам не стрічку ’5′, а число 5.

 

1

    return input(question) - 1

Після зміненого рядочка наша програма виглядатиме наступним чином:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# -*- coding: utf-8 -*-

# функція меню

def menu(list, question):

    for entry in list:

        print 1 + list.index(entry),

        print ") " + entry

 

    return input(question) - 1

 

# визначаэмо наш список опцій для меню

options = ['A','B','C','D','E','F','H','I']

 

# викликаємо нашу функцію

answer = menu(options, 'Яка ваша улюблена літера? ')

 

print 'Ваша відповідь ' + (options[answer])

І має тепер пряцювати. Спробуйте запустити її і переконатися, що все працює правильно і без поломок. Вдалося?

Отже, помилку вирішено!

Винятки (Exceptions, Ексепшини) – Обмеження Коду

Гаразд. Знаємо, що програма зазвичай працює добре, якщо ми не заставляємо її робити якихось дивних речей Опис : :-) Але що, якщо спробувати? Наприклад, запускаємо нашу програму і “випадково” передаємо в меню програми не число, а літеру. Упс!

 

1

2

3

4

5

6

7

Traceback (most recent call last):

  File "test.py", line 14, in <module>

    answer = menu(options, 'Яка ваша улюблена літера? ')

  File "test.py", line 8, in menu

    return input(question) - 1

  File "<string>", line 1, in <module>

NameError: name 'l' is not defined

У прикладі вище я передав нашій програмі літеру ‘l’, і отримав таку помилку (трейсбек). Що вона нам каже? В трейсбеку можемо бачити наведено два рядочки коду. Один в рядочку 8 і інший в рядочку 14.

Давайте спробуємо з'ясувати, в чому проблема. Маємо NameError, який каже нам, що змінна під назвою ‘l’ не визначена. Якщо ще пам'ятати, перед отриманням даної помилки я ввів в меню літеру ‘l’. Зауважили зв’язок? Опис : :-)

Справа в тому, що функція ‘input’ при конвертації, отримавши символ чи стрічку, пробує трактувати дану стрічку як назву змінної у нашій програмі. Зрозуміло, що ми не визначали ніякої змінної під назвою ‘l’, тому отримуємо помилку типу ‘NameError’. Тобто, якщо користувач введе у меню нашої програми що-небудь окрім чисел від 1 до 8 – він зазвичай отримає помилку.

Це погано! Що ж будемо з цим робити? Одним з найкращих та простих варіантів обробки таких ситуацій є використання пари операторів try та except. Давайте одразу до швидкого прикладу, а потім вже розберемо його:

 

1

2

3

4

try:

    function(parameter1, parameter2)

except:

    print 'Щось не працює!'

Це є приклад використання пари операторів ‘try’, ‘except’, щоб відловити та обробити помилку, при цьому не показавши її на зовні користувачеві. Ми запускаємо наш код, той який може зламатися за певних умов, всередині оператора ‘try:’. Другою гілкою буде ‘except:’, її тілом є код, який запуститься у випадку, якщо тіло оператора ‘try:’ таки видасть програмну помилку. В протилежному випадку код всередині оператора ‘except:’ запущений не буде, і наша програма піде собі далі по коду.

Тобто, try-except пара працює подібно до if-else, але не має аргументом логічну умову (логічний вираз), а слідкує чи не поламається код всередині тіла оператора ‘try:’.

Тепер давайте спробуємо використати нашу пару операторів ‘try’ – ‘except’ у нашій попередньо визначеній функції ‘menu’, таким чином, щоб замість отримання поломки, ми б отримували гарне повідомлення на екран про неправильний ввід користувача:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

# -*- coding: utf-8 -*-

# функція меню

def menu(list, question):

    for entry in list:

        print 1 + list.index(entry),

        print ") " + entry

 

    try:

        return input(question) - 1

    except NameError:

        print 'Будь-ласка, введіть число від 1 до 8'

 

# визначаэмо наш список опцій для меню

options = ['A','B','C','D','E','F','H','I']

 

# викликаємо нашу функцію

answer = menu(options, 'Яка ваша улюблена літера? ')

 

print 'Ваша відповідь ' + (options[answer])

Зверніть увагу. Ми скористалися оператором except у вигляді:

 

1

except NameError:

Це означає, що ми не ловимо усі помилки, а лише помилки з типом NameError. Без такого аргументу наш оператор ‘except’ зловить для нас усі-усі помилки, що трапляться в тілі оператора ‘try’.

А ну тепер спробуйте запустити нашу оновлену програму і замість числа 1-8 введіть будь-яку літеру. Що бачите? Саме так! Спробували пофіксити одну помилку, а отримали іншу. Але тепер бачимо, що вона сталася вже далі по коду. Тобто поперднє місце поломки з допомогою операторі try/except нам вдалося пройти. Так часто буває 

Отже, давайте глянемо детальніше на нову помилку:

 

1

2

3

4

Traceback (most recent call last):

  File "/Users/vipod/Desktop/text.py", line 19, in <module>

    print 'Ваша відповідь ' + (options[answer])

TypeError: list indices must be integers, not NoneType

Які ідеї, чому цього разу трапилася помилка?

Проблема в тому, що наша програма очікує від функції ‘menu’ саме числа, яке потім ми з вами використовуємо як індекс для пошуку серед опцій: ‘optionі[answer]‘. Що ж змінилося? А те, що у випадку попередньої помилки ми її відловлюємо та натомість того щоб що-небудь повернути з функції, ми просто друкуємо повідомлення на екран. А у мові Пітон, якщо нічого не повертати явно з функції (не використати оператор ‘return’), тоді функція автоматично повертає ‘None’ – порожнє значення. Ну і зрозуміло, що спроба отримати елемент зі списку ‘options’ під індексом ‘None’ (options[None]) закінчується невдачею. Адже в Пітоні елементи списку пронумеровані числами починаючи з нуля і ніякого None там немає 

Що ж робити далі? Є як мінімум два варіанти:

1.    скористатися операторами умови ‘if’/’else’, та перевіряти чи ми отримали None замість числа з функції ‘menu’. Якщо так – не пробуємо отримати опцію з меню, а друкуємо ще одне повідомлення з програми

2.    скористатися операторами ‘try’/’except’, щоб зловити тепер нашу другу помилку та знову ж таки вивести повідомлення на екран у випадку поломки

Оберемо другий варіант для закріплення знань по оператору ‘try’. Ось як виглядатиме наша програма з використаними операторами ‘try’/’except’ вже вдруге:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# -*- coding: utf-8 -*-

# функція меню

def menu(list, question):

    for entry in list:

        print 1 + list.index(entry),

        print ") " + entry

 

    try:

        return input(question) - 1

    except NameError:

        print 'Будь-ласка, введіть число від 1 до 8'

 

# визначаэмо наш список опцій для меню

options = ['A','B','C','D','E','F','H','I']

 

# викликаємо нашу функцію

answer = menu(options, 'Яка ваша улюблена літера? ')

 

try:

    print 'Ваша відповідь ' + (options[answer])

except:

    print 'Неправильна відповідь. Спробуйте ще раз.'

Вуаля! Все працює, проблему вирішено!

Тепер ви майже гуру у вирішенні проблем при програмування мовою Python. А це дуже важливо, адже програміст – це впершу чергу людина, яка вміє вирішувати виникаючи проблеми, а не просто знає мову програмування.

Happy End

Є питання по уроку? Прошу задавати в коментарях – будемо розбиратись!

На цьому все! Це наш останній урок з вивчення мови програмування Python версія 2! Урааа! Вітаю з успішним проходженням, так тримати! Надіюсь було корисно!

Що далі? А далі або рухаємось до поглиблених спеціалізованих курсів та матеріалів по мові Пітон, якими інтернет прямо таки ‘кишить’. Або, якщо плануєте програмувати під веб, тоді раджу тепер переходити до освоєння азів мови веб розмітки HTML!

Чекаю на ваші коментарі:

 

 

Коментарі  

# MatVect 08.06.2018, 01:11
Buy Mitazapine In Uk cheapest cialis Viagra Sin Receta Levitra Where To Order Pyridium Geridium No Rx
Відповісти | Відповісти цитуючи | Цитата

Додати коментар

Захисний код
Оновити

   

Поділіться з друзями

 
   

Сайт для перевірки своїх знань з програмування на сайті:http://www.quizful.net/test


 Розробка сайтів, інтернет-магазинів під ключ. Створення програмного забезпечення для обліку в магазинах,

гуртовнях, ведення власного бізнесу та інших. Написання дипломних та курсових робіт з програмування, баз даних.

 

Звертайтесь за адресою email:kuzbyt@ukr.net

 

 

© (C) Sambir, I.Kuzbyt