From 19be7aef5351e2bdc98d5ce35962ee02104c795d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milaan=20Parmar=20/=20=20=D0=9C=D0=B8=D0=BB=D0=B0=D0=BD=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D0=BC=D0=B0=D1=80=20/=20=5F=E7=B1=B3?= =?UTF-8?q?=E5=85=B0=20=E5=B8=95=E5=B0=94=E9=A9=AC?= Date: Fri, 25 Jun 2021 12:27:21 +0530 Subject: [PATCH] Add files via upload --- 001_Python_File_Input_Output.ipynb | 918 +++++++++++++++++++++++ 002_Python_File_Directory.ipynb | 705 +++++++++++++++++ 003_Python_File_Exception.ipynb | 268 +++++++ 004_Python_Exceptions_Handling.ipynb | 766 +++++++++++++++++++ 005_Python_User_defined_Exceptions.ipynb | 464 ++++++++++++ 5 files changed, 3121 insertions(+) create mode 100644 001_Python_File_Input_Output.ipynb create mode 100644 002_Python_File_Directory.ipynb create mode 100644 003_Python_File_Exception.ipynb create mode 100644 004_Python_Exceptions_Handling.ipynb create mode 100644 005_Python_User_defined_Exceptions.ipynb diff --git a/001_Python_File_Input_Output.ipynb b/001_Python_File_Input_Output.ipynb new file mode 100644 index 0000000..77f7e93 --- /dev/null +++ b/001_Python_File_Input_Output.ipynb @@ -0,0 +1,918 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/05_Python_Files)**\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python File I/O\n", + "\n", + "In this class, you'll learn about Python file operations. More specifically, opening a file, reading from it, writing into it, closing it, and various file methods that you should be aware of." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Files\n", + "\n", + "Files are named locations on disk to store related information. They are used to permanently store data in a non-volatile memory (e.g. hard disk).\n", + "\n", + "Since Random Access Memory (RAM) is volatile (which loses its data when the computer is turned off), we use files for future use of the data by permanently storing them.\n", + "\n", + "When we want to read from or write to a file, we need to open it first. When we are done, it needs to be closed so that the resources that are tied with the file are freed.\n", + "\n", + "Hence, in Python, a file operation takes place in the following order:\n", + "\n", + "1. Open a file\n", + "2. Close the file\n", + "3. Read or write (perform operation)\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Opening Files in Python\n", + "\n", + "Python has a built-in **`open()`** function to open a file. This function returns a file object, also called a handle, as it is used to read or modify the file accordingly.\n", + "\n", + "```python\n", + ">>> f = open(\"test.txt\") # open file in current directory\n", + ">>> f = open(\"C:/Python99/README.txt\") # specifying full path\n", + "```\n", + "\n", + "We can specify the mode while opening a file. In mode, we specify whether we want to read **`r`**, write **`w`** or append **`a`** to the file. We can also specify if we want to open the file in text mode or binary mode.\n", + "\n", + "The default is reading in text mode. In this mode, we get strings when reading from the file.\n", + "\n", + "On the other hand, binary mode returns bytes and this is the mode to be used when dealing with non-text files like images or executable files.\n", + "\n", + "| Mode | Description |\n", + "|:----:| :--- |\n", + "| **`r`** | Opens a file for reading only. The file pointer is placed at the beginning of the file. This is the default mode. | \n", + "| **`t`** | Opens in text mode. (default). | \n", + "| **`b`** | Opens in binary mode. | \n", + "| **`x`** | Opens a file for exclusive creation. If the file already exists, the operation fails. | \n", + "| **`rb`** | Opens a file for reading only in binary format. The file pointer is placed at the beginning of the file. This is the default mode. | \n", + "| **`r+`** | Opens a file for both reading and writing. The file pointer placed at the beginning of the file. | \n", + "| **`rb+`** | Opens a file for both reading and writing in binary format. The file pointer placed at the beginning of the file. | \n", + "| **`w`** | Opens a file for writing only. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing. | \n", + "| **`wb`** | Opens a file for writing only in binary format. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing. | \n", + "| **`w+`** | Opens a file for both writing and reading. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing. | \n", + "| **`wb+`** | Opens a file for both writing and reading in binary format. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing. | \n", + "| **`a`** | Opens a file for appending. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing. | \n", + "| **`ab`** | Opens a file for appending in binary format. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing. | \n", + "| **`a+`** | Opens a file for both appending and reading. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing. |\n", + "| **`ab+`** | Opens a file for both appending and reading in binary format. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing. | " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:33:59.892237Z", + "start_time": "2021-06-18T15:33:59.884426Z" + } + }, + "outputs": [], + "source": [ + "f = open(\"test.txt\") # equivalent to 'r' or 'rt'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:00.640278Z", + "start_time": "2021-06-18T15:34:00.635397Z" + } + }, + "outputs": [], + "source": [ + "f = open(\"test.txt\",'w') # write in text mode" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:01.153947Z", + "start_time": "2021-06-18T15:34:01.134419Z" + } + }, + "outputs": [], + "source": [ + "f = open(\"logo.png\",'r+b') # read and write in binary mode" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike other languages, the character **`a`** does not imply the number 97 until it is encoded using **`ASCII`** (or other equivalent encodings).\n", + "\n", + "Moreover, the default encoding is platform dependent. In windows, it is **`cp1252`** but **`utf-8`** in Linux.\n", + "\n", + "So, we must not also rely on the default encoding or else our code will behave differently in different platforms.\n", + "\n", + "Hence, when working with files in text mode, it is highly recommended to specify the encoding type." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:05.598733Z", + "start_time": "2021-06-18T15:34:05.587019Z" + } + }, + "outputs": [], + "source": [ + "f = open(\"test.txt\", mode='r', encoding='utf-8')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Closing Files in Python\n", + "\n", + "When we are done with performing operations on the file, we need to properly close the file.\n", + "\n", + "Closing a file will free up the resources that were tied with the file. It is done using the **`close()`** method available in Python.\n", + "\n", + "Python has a garbage collector to clean up unreferenced objects but we must not rely on it to close the file." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:06.985930Z", + "start_time": "2021-06-18T15:34:06.979096Z" + } + }, + "outputs": [], + "source": [ + "f = open(\"test.txt\", encoding = 'utf-8')\n", + "# perform file operations\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This method is not entirely safe. If an exception occurs when we are performing some operation with the file, the code exits without closing the file.\n", + "\n", + "A safer way is to use a **[try-finally](https://github.com/milaan9/05_Python_Files/blob/main/004_Python_Exceptions_Handling.ipynb)** block." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:08.405351Z", + "start_time": "2021-06-18T15:34:08.387777Z" + } + }, + "outputs": [], + "source": [ + "try:\n", + " f = open(\"test.txt\", encoding = 'utf-8')\n", + " # perform file operations\n", + "finally:\n", + " f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This way, we are guaranteeing that the file is properly closed even if an exception is raised that causes program flow to stop.\n", + "\n", + "The best way to close a file is by using the **`with`** statement. This ensures that the file is closed when the block inside the **`with`** statement is exited.\n", + "\n", + "We don't need to explicitly call the **`close()`** method. It is done internally.\n", + "\n", + "```python\n", + ">>>with open(\"test.txt\", encoding = 'utf-8') as f:\n", + " # perform file operations\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The file Object Attributes\n", + "\n", + "* **file.closed** - Returns true if file is closed, false otherwise.\n", + "* **file.mode** - Returns access mode with which file was opened.\n", + "* **file.name** - Returns name of the file." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:11.108946Z", + "start_time": "2021-06-18T15:34:11.098205Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Name of the file: data.txt\n", + "Closed or not : False\n", + "Opening mode : wb\n" + ] + } + ], + "source": [ + "# Open a file\n", + "data = open(\"data.txt\", \"wb\")\n", + "print (\"Name of the file: \", data.name)\n", + "print (\"Closed or not : \", data.closed)\n", + "print (\"Opening mode : \", data.mode)\n", + "data.close() #closed data.txt file" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Writing to Files in Python\n", + "\n", + "In order to write into a file in Python, we need to open it in write **`w`**, append **`a`** or exclusive creation **`x`** mode.\n", + "\n", + "We need to be careful with the **`w`** mode, as it will overwrite into the file if it already exists. Due to this, all the previous data are erased.\n", + "\n", + "Writing a string or sequence of bytes (for binary files) is done using the **`write()`** method. This method returns the number of characters written to the file." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:17.998538Z", + "start_time": "2021-06-18T15:34:17.979009Z" + } + }, + "outputs": [], + "source": [ + "with open(\"test_1.txt\",'w',encoding = 'utf-8') as f:\n", + " f.write(\"my first file\\n\")\n", + " f.write(\"This file\\n\\n\")\n", + " f.write(\"contains three lines\\n\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This program will create a new file named **`test_1.txt`** in the current directory if it does not exist. If it does exist, it is overwritten.\n", + "\n", + "We must include the newline characters ourselves to distinguish the different lines." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:21.520483Z", + "start_time": "2021-06-18T15:34:21.515603Z" + } + }, + "outputs": [], + "source": [ + "with open(\"test_2.txt\",'w',encoding = 'utf-8') as f:\n", + " f.write(\"This is file\\n\")\n", + " f.write(\"my\\n\")\n", + " f.write(\"first file\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:22.612276Z", + "start_time": "2021-06-18T15:34:22.595674Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "done\n" + ] + } + ], + "source": [ + "# open a file in current directory\n", + "data = open(\"data_1.txt\", \"w\") # \"w\" write in text mode,\n", + "data.write(\"Welcome to Dr. Milan Parmar's Python Tutorial\")\n", + "print(\"done\")\n", + "data.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Reading Files in Python\n", + "\n", + "To read a file in Python, we must open the file in reading **`r`** mode.\n", + "\n", + "There are various methods available for this purpose. We can use the **`read(size)`** method to read in the **`size`** number of data. If the **`size`** parameter is not specified, it reads and returns up to the end of the file.\n", + "\n", + "We can read the **`text_1.txt`** file we wrote in the above section in the following way:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:37.419777Z", + "start_time": "2021-06-18T15:34:37.397313Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'my first'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f = open(\"test_1.txt\",'r',encoding = 'utf-8')\n", + "f.read(8) # read the first 8 data characters" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:38.371914Z", + "start_time": "2021-06-18T15:34:38.364105Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "' file'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.read(5) # read the next 5 data characters" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:38.853355Z", + "start_time": "2021-06-18T15:34:38.837734Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nThis file\\n\\ncontains three lines\\n'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.read() # read in the rest till end of file" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:39.275232Z", + "start_time": "2021-06-18T15:34:39.261561Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "''" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.read() # further reading returns empty sting" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can see that the **`read()`** method returns a newline as **`'\\n'`**. Once the end of the file is reached, we get an empty string on further reading.\n", + "\n", + "We can change our current file cursor (position) using the **`seek()`** method. Similarly, the **`tell()`** method returns our current position (in number of bytes)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:39.977372Z", + "start_time": "2021-06-18T15:34:39.965655Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "50" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.tell() # get the current file position" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:40.257643Z", + "start_time": "2021-06-18T15:34:40.239090Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.seek(0) # bring file cursor to initial position" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:40.645334Z", + "start_time": "2021-06-18T15:34:40.639476Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "my first file\n", + "This file\n", + "\n", + "contains three lines\n", + "\n" + ] + } + ], + "source": [ + "print(f.read()) # read the entire file" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can read a file line-by-line using a **[for loop](https://github.com/milaan9/03_Python_Flow_Control/blob/main/005_Python_for_Loop.ipynb)**. This is both efficient and fast." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:44.541300Z", + "start_time": "2021-06-18T15:34:44.532516Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "my first file\n", + "This file\n", + "\n", + "contains three lines\n" + ] + } + ], + "source": [ + "f = open(\"test_1.txt\",'r',encoding = 'utf-8')\n", + "for line in f:\n", + " print(line, end = '')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this program, the lines in the file itself include a newline character **`\\n`**. So, we use the end parameter of the **`print()`** function to avoid two newlines when printing." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, we can use the **`readline()`** method to read individual lines of a file. This method reads a file till the newline, including the newline character." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:46.631127Z", + "start_time": "2021-06-18T15:34:46.611600Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'my first file\\n'" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.seek(0) # bring file cursor to initial position\n", + "f.readline()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:47.098896Z", + "start_time": "2021-06-18T15:34:47.078394Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'This file\\n'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.readline()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:47.597430Z", + "start_time": "2021-06-18T15:34:47.579852Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\n'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.readline()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:49.810301Z", + "start_time": "2021-06-18T15:34:49.796633Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'contains three lines\\n'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.readline()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lastly, the **`readlines()`** method returns a list of remaining lines of the entire file. All these reading methods return empty values when the end of file **(EOF)** is reached." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:52.456765Z", + "start_time": "2021-06-18T15:34:52.437237Z" + }, + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['my first file\\n', 'This file\\n', '\\n', 'contains three lines\\n']" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f.seek(0) # bring file cursor to initial position\n", + "f.readlines()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:34:54.966025Z", + "start_time": "2021-06-18T15:34:54.956260Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Welcome to Dr. Milan Parmar\n", + "'s Python Tutorial\n" + ] + } + ], + "source": [ + "# Open a file\n", + "data = open(\"data_1.txt\", \"r+\")\n", + "file_data = data.read(27) # read 3.375 byte only\n", + "full_data = data.read() # read all byte into file from last cursor\n", + "print(file_data)\n", + "print(full_data)\n", + "data.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## File Positions\n", + "\n", + "The **`tell()`** method tells you the current position within the file; in other words, the next read or write will occur at that many bytes from the beginning of the file.\n", + "\n", + "The **`seek(offset[, from])`** method changes the current file position. The offset argument indicates the number of bytes to be moved. The from argument specifies the reference position from where the bytes are to be moved.\n", + "\n", + "If from is set to 0, the beginning of the file is used as the reference position. If it is set to 1, the current position is used as the reference position. If it is set to 2 then the end of the file would be taken as the reference position." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:02.590964Z", + "start_time": "2021-06-18T15:35:02.572412Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "current position after reading 27 byte : 27\n", + "Welcome to Dr. Milan Parmar\n", + "Welcome to Dr. Milan Parmar's Python Tutorial\n", + "position after reading file : 45\n" + ] + } + ], + "source": [ + "# Open a file\n", + "data = open(\"data_1.txt\", \"r+\")\n", + "file_data = data.read(27) # read 18 byte only\n", + "print(\"current position after reading 27 byte :\",data.tell())\n", + "data.seek(0) #here current position set to 0 (starting of file)\n", + "full_data = data.read() #read all byte\n", + "print(file_data)\n", + "print(full_data)\n", + "print(\"position after reading file : \",data.tell())\n", + "data.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Python File Methods\n", + "\n", + "There are various methods available with the file object. Some of them have been used in the above examples.\n", + "\n", + "Here is the complete list of methods in text mode with a brief description:\n", + "\n", + "| Method | Description |\n", + "|:----| :--- |\n", + "| **`close()`** | Closes an opened file. It has no effect if the file is already closed. | \n", + "| **`detach()`** | Separates the underlying binary buffer from the **`TextIOBase`** and returns it. | \n", + "| **`fileno()`** | Returns an integer number (file descriptor) of the file. | \n", + "| **`flush()`** | Flushes the write buffer of the file stream. | \n", + "| **`isatty()`** | Returns **`True`** if the file stream is interactive. | \n", + "| **`read(n)`** | Reads at most `n` characters from the file. Reads till end of file if it is negative or `None`. | \n", + "| **`readable()`** | Returns **`True`** if the file stream can be read from. | \n", + "| **`readline(n=-1)`** | Reads and returns one line from the file. Reads in at most **`n`** bytes if specified. | \n", + "| **`readlines(n=-1)`** | Reads and returns a list of lines from the file. Reads in at most **`n`** bytes/characters if specified. | \n", + "| **`seek(offset,from=SEEK_SET)`** | Changes the file position to **`offset`** bytes, in reference to `from` (start, current, end). | \n", + "| **`seekable()`** | Returns **`True`** if the file stream supports random access. | \n", + "| **`tell()`** | Returns the current file location. | \n", + "| **`truncate(size=None)`** | Resizes the file stream to **`size`** bytes. If **`size`** is not specified, resizes to current location.. | \n", + "| **`writable()`** | Returns **`True`** if the file stream can be written to. | \n", + "| **`write(s)`** | Writes the string **`s`** to the file and returns the number of characters written.. | \n", + "| **`writelines(lines)`** | Writes a list of **`lines`** to the file.. | " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "204.797px" + }, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/002_Python_File_Directory.ipynb b/002_Python_File_Directory.ipynb new file mode 100644 index 0000000..238655b --- /dev/null +++ b/002_Python_File_Directory.ipynb @@ -0,0 +1,705 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/05_Python_Files)**\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Directory and Files Management\n", + "\n", + "In this class, you'll learn about file and directory management in Python, i.e. creating a directory, renaming it, listing all directories, and working with them.\n", + "\n", + "## Python Directory\n", + "\n", + "If there are a large number of **[files](https://github.com/milaan9/05_Python_Files/blob/main/001_Python_File_Input_Output.ipynb)** to handle in our Python program, we can arrange our code within different directories to make things more manageable.\n", + "\n", + "A directory or folder is a collection of files and subdirectories. Python has the **`os`** **[module](https://github.com/milaan9/04_Python_Functions/blob/main/007_Python_Function_Module.ipynb)** that provides us with many useful methods to work with directories (and files as well)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Current Directory `getcwd()` - \n", + "\n", + "We can get the present working directory using the **`getcwd()`** method of the os module.\n", + "\n", + "This method returns the current working directory in the form of a string. We can also use the **`getcwd()`** method to get it as bytes object." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:18.948260Z", + "start_time": "2021-06-18T15:35:18.942401Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C:\\Users\\Deepak\\01_Learn_Python4Data\\05_Python_Files\n" + ] + } + ], + "source": [ + "import os\n", + "print(os.getcwd())" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:20.242197Z", + "start_time": "2021-06-18T15:35:20.220713Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "b'C:\\\\Users\\\\Deepak\\\\01_Learn_Python4Data\\\\05_Python_Files'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os\n", + "os.getcwdb()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The extra backslash implies an escape sequence. The **`print()`** function will render this properly." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Changing Directory `chdir()` - \n", + "\n", + "We can change the current working directory by using the **`chdir()`** method.\n", + "\n", + "The new path that we want to change into must be supplied as a string to this method. We can use both the forward-slash **`/`** or the backward-slash **`\\`** to separate the path elements.\n", + "\n", + "It is safer to use an escape sequence when using the backward slash.\n", + "\n", + "**Syntax:**\n", + "\n", + "**`os.chdir(\"newdir\")`**\n", + "\n", + ">**Remember to**: \n", + "1. First copy the path for current working directory \n", + "2. Windows user and MacOS users, first create an empty folder with name \"**xyz**\" on your desktop." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:41.789882Z", + "start_time": "2021-06-18T15:35:41.773772Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Directory changed\n", + "C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\n" + ] + } + ], + "source": [ + "import os\n", + "\n", + "# Changing a directory to \"C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\"\n", + "os.chdir(r\"C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\") \n", + " \n", + "print(\"Directory changed\") \n", + "\n", + "print(os.getcwd())" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:44.970521Z", + "start_time": "2021-06-18T15:35:44.950018Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\n" + ] + } + ], + "source": [ + "import os\n", + "print(os.getcwd())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:45.765437Z", + "start_time": "2021-06-18T15:35:45.749818Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Directory changed\n" + ] + } + ], + "source": [ + "import os\n", + "\n", + "# Changing a directory back to original directory \"C:\\Users\\Deepak\\01_Learn_Python4Data\\05_Python_Files\"\n", + "os.chdir(r\"C:\\Users\\Deepak\\01_Learn_Python4Data\\05_Python_Files\") \n", + " \n", + "print(\"Directory changed\") " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:47.044728Z", + "start_time": "2021-06-18T15:35:47.037894Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C:\\Users\\Deepak\\01_Learn_Python4Data\\05_Python_Files\n" + ] + } + ], + "source": [ + "import os\n", + "print(os.getcwd())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List Directories and Files `listdir()` - \n", + "\n", + "The **`listdir()`** method displays all files and sub-directories inside a directory.\n", + "\n", + "This method takes in a path and returns a list of subdirectories and files in that path. If no path is specified, it returns the list of subdirectories and files from the current working directory." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:50.849874Z", + "start_time": "2021-06-18T15:35:50.830348Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C:\\Users\\Deepak\\01_Learn_Python4Data\\05_Python_Files\n" + ] + }, + { + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " '001_Python_File_Input_Output.ipynb',\n", + " '002_Python_File_Directory.ipynb',\n", + " '003_Python_File_Exception.ipynb',\n", + " '004_Python_Exceptions_Handling.ipynb',\n", + " '005_Python_User_defined_Exceptions.ipynb',\n", + " 'data.txt',\n", + " 'data_1.txt',\n", + " 'img',\n", + " 'logo.png',\n", + " 'logo1.png',\n", + " 'test.txt',\n", + " 'testfile',\n", + " 'test_1.txt',\n", + " 'test_2.txt']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(os.getcwd())\n", + "\n", + "os.listdir()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:35:55.791730Z", + "start_time": "2021-06-18T15:35:55.775132Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['$Recycle.Bin',\n", + " '$WinREAgent',\n", + " '$WINRE_BACKUP_PARTITION.MARKER',\n", + " 'bootTel.dat',\n", + " 'Documents and Settings',\n", + " 'DumpStack.log',\n", + " 'DumpStack.log.tmp',\n", + " 'hiberfil.sys',\n", + " 'ImDisk',\n", + " 'OneDriveTemp',\n", + " 'pagefile.sys',\n", + " 'PerfLogs',\n", + " 'Program Files',\n", + " 'Program Files (x86)',\n", + " 'ProgramData',\n", + " 'Python99',\n", + " 'Recovery',\n", + " 'swapfile.sys',\n", + " 'System Volume Information',\n", + " 'Users',\n", + " 'Windows']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "os.listdir('C:\\\\')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Making a New Directory `mkdir()` - \n", + "\n", + "You can use the **`mkdir()`** method of the os module to create directories in the current directory. You need to supply an argument to this method, which contains the name of the directory to be created.\n", + "\n", + "This method takes in the path of the new directory. If the full path is not specified, the new directory is created in the current working directory.\n", + "\n", + "**Syntax:**\n", + "\n", + "**`os.mkdir(\"dir_name\")`**" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:36:04.319983Z", + "start_time": "2021-06-18T15:36:04.301919Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Directory created\n" + ] + }, + { + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " '001_Python_File_Input_Output.ipynb',\n", + " '002_Python_File_Directory.ipynb',\n", + " '003_Python_File_Exception.ipynb',\n", + " '004_Python_Exceptions_Handling.ipynb',\n", + " '005_Python_User_defined_Exceptions.ipynb',\n", + " 'data.txt',\n", + " 'data_1.txt',\n", + " 'img',\n", + " 'logo.png',\n", + " 'logo1.png',\n", + " 'python_study',\n", + " 'test.txt',\n", + " 'testfile',\n", + " 'test_1.txt',\n", + " 'test_2.txt']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os\n", + "os.mkdir('python_study')\n", + "print(\"Directory created\") \n", + "\n", + "os.listdir()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Renaming a Directory or a File `rename()` - \n", + "\n", + "The **`rename()`** method can rename a directory or a file.\n", + "\n", + "**Syntax:**\n", + "\n", + "**`os.rename(current_file_name, new_file_name)`**" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:36:08.074352Z", + "start_time": "2021-06-18T15:36:08.062629Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Directory renamed\n" + ] + }, + { + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " '001_Python_File_Input_Output.ipynb',\n", + " '002_Python_File_Directory.ipynb',\n", + " '003_Python_File_Exception.ipynb',\n", + " '004_Python_Exceptions_Handling.ipynb',\n", + " '005_Python_User_defined_Exceptions.ipynb',\n", + " 'data.txt',\n", + " 'data_1.txt',\n", + " 'img',\n", + " 'logo.png',\n", + " 'logo1.png',\n", + " 'python_learning',\n", + " 'test.txt',\n", + " 'testfile',\n", + " 'test_1.txt',\n", + " 'test_2.txt']" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "os.listdir()\n", + "\n", + "os.rename('python_study','python_learning')\n", + "print(\"Directory renamed\") \n", + "\n", + "os.listdir()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:36:20.064003Z", + "start_time": "2021-06-18T15:36:20.055216Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "file renamed\n" + ] + } + ], + "source": [ + "import os\n", + "os.rename('data_1.txt','my_data.txt')\n", + "print(\"file renamed\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Removing a Directory or a File `remove()` and `rmdir()` - \n", + "\n", + "A file can be removed (deleted) using the **`remove()`** method.\n", + "Similarly, the **`rmdir()`** method removes an empty directory. Before removing a directory, all the contents in it should be removed." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:36:32.627869Z", + "start_time": "2021-06-18T15:36:32.598577Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Directory deleted\n" + ] + }, + { + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " '001_Python_File_Input_Output.ipynb',\n", + " '002_Python_File_Directory.ipynb',\n", + " '003_Python_File_Exception.ipynb',\n", + " '004_Python_Exceptions_Handling.ipynb',\n", + " '005_Python_User_defined_Exceptions.ipynb',\n", + " 'data.txt',\n", + " 'img',\n", + " 'logo.png',\n", + " 'logo1.png',\n", + " 'my_data.txt',\n", + " 'python_learning',\n", + " 'test.txt',\n", + " 'testfile',\n", + " 'test_1.txt',\n", + " 'test_2.txt']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os\n", + "\n", + "# This would remove \"C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\" directory.\n", + "os.rmdir(r\"C:\\Users\\Deepak\\OneDrive\\Desktop\\xyz\")\n", + "print(\"Directory deleted\") \n", + "\n", + "os.listdir()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:36:40.443239Z", + "start_time": "2021-06-18T15:36:40.432499Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "file deleted\n" + ] + } + ], + "source": [ + "import os\n", + "os.remove('my_data.txt')\n", + "print(\"file deleted\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ">**Note**: The **`rmdir()`** method can only remove empty directories." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to remove a non-empty directory, we can use the **`rmtree()`** method inside the **`shutil`** module." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:37:00.249730Z", + "start_time": "2021-06-18T15:37:00.241919Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['.ipynb_checkpoints',\n", + " '001_Python_File_Input_Output.ipynb',\n", + " '002_Python_File_Directory.ipynb',\n", + " '003_Python_File_Exception.ipynb',\n", + " '004_Python_Exceptions_Handling.ipynb',\n", + " '005_Python_User_defined_Exceptions.ipynb',\n", + " 'data.txt',\n", + " 'img',\n", + " 'logo.png',\n", + " 'logo1.png',\n", + " 'test.txt',\n", + " 'testfile',\n", + " 'test_1.txt',\n", + " 'test_2.txt']" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import shutil\n", + "\n", + "shutil.rmtree('python_learning')\n", + "os.listdir()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/003_Python_File_Exception.ipynb b/003_Python_File_Exception.ipynb new file mode 100644 index 0000000..3918247 --- /dev/null +++ b/003_Python_File_Exception.ipynb @@ -0,0 +1,268 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/05_Python_Files)**\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Errors and Built-in Exceptions\n", + "\n", + "In this class, you will learn about different types of errors and exceptions that are built-in to Python. They are raised whenever the Python interpreter encounters errors.\n", + "\n", + "We can make certain mistakes while writing a program that lead to errors when we try to run it. A python program terminates as soon as it encounters an unhandled error. These errors can be broadly classified into two classes:\n", + "\n", + "1. Syntax errors\n", + "2. Logical errors (Exceptions)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Python Syntax Errors\n", + "\n", + "Error caused by not following the proper structure (syntax) of the language is called **syntax error** or **parsing error**.\n", + "\n", + "For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:39:26.584572Z", + "start_time": "2021-06-18T15:39:26.566021Z" + }, + "scrolled": true + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m if a < 3\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "if a < 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As shown in the example, an arrow indicates where the parser ran into the syntax error.\n", + "\n", + "We can notice here that a colon **`:`** is missing in the **`if`** statement." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Python Logical Errors (Exceptions)\n", + "\n", + "Errors that occur at runtime (after passing the syntax test) are called **exceptions** or **logical errors**.\n", + "\n", + "For instance, they occur when we try to open a file(for reading) that does not exist (**`FileNotFoundError`**), try to divide a number by zero (**`ZeroDivisionError`**), or try to import a module that does not exist (**`ImportError`**).\n", + "\n", + "Whenever these types of runtime errors occur, Python creates an exception object. If not handled properly, it prints a traceback to that error along with some details about why that error occurred.\n", + "\n", + "Let's look at how Python treats these errors:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:39:28.907309Z", + "start_time": "2021-06-18T15:39:28.612394Z" + } + }, + "outputs": [ + { + "ename": "ZeroDivisionError", + "evalue": "division by zero", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m1\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" + ] + } + ], + "source": [ + "1 / 0" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:39:32.662651Z", + "start_time": "2021-06-18T15:39:32.644100Z" + } + }, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'imaginary.txt'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"imaginary.txt\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'imaginary.txt'" + ] + } + ], + "source": [ + "open(\"imaginary.txt\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Python Built-in Exceptions\n", + "\n", + "Illegal operations can raise exceptions. There are plenty of built-in exceptions in Python that are raised when corresponding errors occur. We can view all the built-in exceptions using the built-in **`local()`** function as follows:\n", + "\n", + "```python\n", + "print(dir(locals()['__builtins__']))\n", + "```\n", + "\n", + "**`locals()['__builtins__']`** will return a module of built-in exceptions, functions, and attributes. **`dir`** allows us to list these attributes as strings.\n", + "\n", + "Some of the common built-in exceptions in Python programming along with the error that cause them are listed below:\n", + "\n", + "| Exception | Cause of Error |\n", + "|:----| :--- |\n", + "| **`AssertionError`** | Raised when an **`assert`** statement fails. | \n", + "| **`AttributeError`** | Raised when attribute assignment or reference fails. | \n", + "| **`EOFError`** | Raised when the **`input()`** function hits end-of-file condition. | \n", + "| **`FloatingPointError`** | Raised when a floating point operation fails. | \n", + "| **`GeneratorExit`** | Raise when a generator's **`close()`** method is called. | \n", + "| **`ImportError`** | Raised when the imported module is not found. | \n", + "| **`IndexError`** | Raised when the index of a sequence is out of range. | \n", + "| **`KeyError`** | Raised when a key is not found in a dictionary. | \n", + "| **`KeyboardInterrupt`** | Raised when the user hits the interrupt key (**`Ctrl+C`** or **`Delete`**). | \n", + "| **`MemoryError`** | Raised when an operation runs out of memory. | \n", + "| **`NameError`** | Raised when a variable is not found in local or global scope. | \n", + "| **`NotImplementedError`** | Raised by abstract methods. | \n", + "| **`OSError`** | Raised when system operation causes system related error. | \n", + "| **`OverflowError`** | Raised when the result of an arithmetic operation is too large to be represented. | \n", + "| **`ReferenceError`** | Raised when a weak reference proxy is used to access a garbage collected referent. | \n", + "| **`RuntimeError`** | Raised when an error does not fall under any other category. | \n", + "| **`StopIteration`** | Raised by **`next()`** function to indicate that there is no further item to be returned by iterator. | \n", + "| **`SyntaxError`** | Raised by parser when syntax error is encountered. | \n", + "| **`IndentationError`** | Raised when there is incorrect indentation. | \n", + "| **`TabError`** | Raised when indentation consists of inconsistent tabs and spaces. | \n", + "| **`SystemError`** | Raised when interpreter detects internal error. | \n", + "| **`SystemExit`** | Raised by **`sys.exit()`** function. | \n", + "| **`TypeError`** | Raised when a function or operation is applied to an object of incorrect type. | \n", + "| **`UnboundLocalError`** | Raised when a reference is made to a local variable in a function or method, but no value has been bound to that variable. | \n", + "| **`UnicodeError`** | Raised when a Unicode-related encoding or decoding error occurs. | \n", + "| **`UnicodeEncodeError`** | Raised when a Unicode-related error occurs during encoding. | \n", + "| **`UnicodeDecodeError`** | Raised when a Unicode-related error occurs during decoding. | \n", + "| **`UnicodeTranslateError`** | Raised when a Unicode-related error occurs during translating. | \n", + "| **`ValueError`** | Raised when a function gets an argument of correct type but improper value. | \n", + "| **`ZeroDivisionError`** | Raised when the second operand of division or modulo operation is zero. | " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If required, we can also define our own exceptions in Python. To learn more about them, visit Python **[User-defined Exceptions](https://github.com/milaan9/05_Python_Files/blob/main/005_Python_User_defined_Exceptions.ipynb)**.\n", + "\n", + "We can handle these built-in and user-defined exceptions in Python using **`try`**, **`except`** and **`finally`** statements. To learn more about them, visit **[Python try, except and finally statements](https://github.com/milaan9/05_Python_Files/blob/main/004_Python_Exceptions_Handling.ipynb)**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/004_Python_Exceptions_Handling.ipynb b/004_Python_Exceptions_Handling.ipynb new file mode 100644 index 0000000..28883bf --- /dev/null +++ b/004_Python_Exceptions_Handling.ipynb @@ -0,0 +1,766 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/05_Python_Files)**\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Exceptions Handling Using `try`, `except` and `finally` statement\n", + "\n", + "In this class, you'll learn how to handle exceptions in your Python program using try, except and finally statements with the help of examples." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exceptions in Python\n", + "\n", + "An **exception** is an event, which occurs during the execution of a program that disrupts the normal flow of the program's instructions. In general, when a Python script encounters a situation that it cannot cope with, it raises an exception. An exception is a Python object that **represents an error**.\n", + "\n", + "Python has many **[built-in exceptions](https://github.com/milaan9/05_Python_Files/blob/main/003_Python_File_Exception.ipynb)** that are raised when your program encounters an error (something in the program goes wrong).\n", + "\n", + "When a Python script raises an exception, it must either handle the exception immediately otherwise it **terminates** and **quits**.\n", + "\n", + "When these exceptions occur, the Python interpreter stops the current process and passes it to the calling process until it is handled. If not handled, the program will crash.\n", + "\n", + "For example, let us consider a program where we have a function **`A`** that calls **[function](https://github.com/milaan9/04_Python_Functions/blob/main/001_Python_Functions.ipynb)** **`B`**, which in turn calls function **`C`**. If an exception occurs in function **`C`** but is not handled in **`C`**, the exception passes to **`B`** and then to **`A`**.\n", + "\n", + "If never handled, an error message is displayed and our program comes to a sudden unexpected halt." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Catching Exceptions in Python\n", + "\n", + "In Python, exceptions can be handled using a **`try`** statement.\n", + "\n", + "The critical operation which can raise an exception is placed inside the **`try`** clause. The code that handles the exceptions is written in the **`except`** clause.\n", + "\n", + "We can thus choose what operations to perform once we have caught the exception. Here is a simple example." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:56:57.984977Z", + "start_time": "2021-06-18T15:56:57.968375Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The entry is a\n", + "Oops! occurred.\n", + "Next entry.\n", + "\n", + "The entry is 0\n", + "Oops! occurred.\n", + "Next entry.\n", + "\n", + "The entry is 2\n", + "The reciprocal of 2 is 0.5\n" + ] + } + ], + "source": [ + "# Example 1:\n", + "\n", + "# import module sys to get the type of exception\n", + "import sys\n", + "\n", + "randomList = ['a', 0, 2]\n", + "\n", + "for entry in randomList:\n", + " try:\n", + " print(\"The entry is\", entry)\n", + " r = 1/int(entry)\n", + " break\n", + " except:\n", + " print(\"Oops!\", sys.exc_info()[0], \"occurred.\")\n", + " print(\"Next entry.\")\n", + " print()\n", + "print(\"The reciprocal of\", entry, \"is\", r)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Explanation:**\n", + "\n", + "In this program, we loop through the values of the **`randomList`** list. As previously mentioned, the portion that can cause an exception is placed inside the **`try`** block.\n", + "\n", + "If no exception occurs, the **`except`** block is skipped and normal flow continues(for last value). But if any exception occurs, it is caught by the **`except`** block (first and second values).\n", + "\n", + "Here, we print the name of the exception using the **`exc_info()`** function inside sys module. We can see that a causes **`ValueError`** and **`0`** causes **`ZeroDivisionError`**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since every exception in Python inherits from the base **`Exception`** class, we can also perform the above task in the following way:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:56:59.650491Z", + "start_time": "2021-06-18T15:56:59.624126Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The entry is a\n", + "Oops! occurred.\n", + "Next entry.\n", + "\n", + "The entry is 0\n", + "Oops! occurred.\n", + "Next entry.\n", + "\n", + "The entry is 2\n", + "The reciprocal of 2 is 0.5\n" + ] + } + ], + "source": [ + "# Example 2:\n", + "\n", + "# This program has the same output as the above program.\n", + "\n", + "# import module sys to get the type of exception\n", + "import sys\n", + "\n", + "randomList = ['a', 0, 2]\n", + "\n", + "for entry in randomList:\n", + " try:\n", + " print(\"The entry is\", entry)\n", + " r = 1/int(entry)\n", + " break\n", + " except Exception as e:\n", + " print(\"Oops!\", e.__class__, \"occurred.\")\n", + " print(\"Next entry.\")\n", + " print()\n", + "print(\"The reciprocal of\", entry, \"is\", r)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Catching Specific Exceptions in Python\n", + "\n", + "In the above example, we did not mention any specific exception in the **`except`** clause.\n", + "\n", + "This is not a good programming practice as it will catch all exceptions and handle every case in the same way. We can specify which exceptions an **`except`** clause should catch.\n", + "\n", + "A **`try`** clause can have any number of **`except`** clauses to handle different exceptions, however, only one will be executed in case an exception occurs.\n", + "\n", + "We can use a tuple of values to specify multiple exceptions in an **`except`** clause. Here is an example pseudo code.\n", + "\n", + "```python\n", + ">>> try:\n", + ">>> # do something\n", + ">>> pass\n", + "\n", + ">>> except ValueError:\n", + ">>> # handle ValueError exception\n", + ">>> pass\n", + "\n", + ">>> except (TypeError, ZeroDivisionError):\n", + ">>> # handle multiple exceptions\n", + ">>> # TypeError and ZeroDivisionError\n", + ">>> pass\n", + "\n", + ">>> except:\n", + ">>> # handle all other exceptions\n", + ">>> pass\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Raising Exceptions in Python\n", + "\n", + "In Python programming, exceptions are raised when errors occur at runtime. We can also manually **`raise`** exceptions using the raise keyword.\n", + "\n", + "We can optionally pass values to the exception to clarify why that exception was raised." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:07.119184Z", + "start_time": "2021-06-18T15:57:06.831592Z" + }, + "scrolled": true + }, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "raise KeyboardInterrupt" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:08.085489Z", + "start_time": "2021-06-18T15:57:08.072795Z" + } + }, + "outputs": [ + { + "ename": "MemoryError", + "evalue": "This is an argument", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mMemoryError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mMemoryError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"This is an argument\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mMemoryError\u001b[0m: This is an argument" + ] + } + ], + "source": [ + "raise MemoryError(\"This is an argument\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:10.749535Z", + "start_time": "2021-06-18T15:57:08.776891Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter a positive integer: 9\n" + ] + } + ], + "source": [ + "try:\n", + " a = int(input(\"Enter a positive integer: \"))\n", + " if a <= 0:\n", + " raise ValueError(\"That is not a positive number!\")\n", + "except ValueError as ve:\n", + " print(ve)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python `try` with `else` clause\n", + "\n", + "In some situations, you might want to run a certain block of code if the code block inside `try` ran without any errors. For these cases, you can use the optional `else` keyword with the `try` statement.\n", + "\n", + ">**Note**: Exceptions in the else clause are not handled by the preceding except clauses.\n", + "\n", + "```python\n", + ">>> try:\n", + ">>> You do your operations here\n", + ">>> ......................\n", + ">>> except ExceptionI:\n", + ">>> If there is ExceptionI, then execute this block.\n", + ">>> except ExceptionII:\n", + ">>> If there is ExceptionII, then execute this block.\n", + ">>> ......................\n", + ">>> else:\n", + ">>> If there is no exception then execute this block.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With our **“Hello, World!”** program written, we are ready to run the program. We’ll use the python3 command along with the name of our program file. Let’s run the program:\n", + "\n", + "* A single try statement can have multiple except statements. This is useful when the **try block** contains statements that may throw different types of exceptions.\n", + "\n", + "* You can also provide a **generic except** clause, which handles any exception. \n", + "\n", + "* After the **except** clause(s), you can include an else-clause. The code in the else-block executes if the code in the try: block does not raise an exception. \n", + "\n", + "* The **else-block** is a good place for code that does not need the try: block's protection." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:13.008305Z", + "start_time": "2021-06-18T15:57:13.000494Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Written content in the file successfully\n" + ] + } + ], + "source": [ + "# Example 1:\n", + "\n", + "try:\n", + " fh = open(\"testfile.txt\", \"w\")\n", + " fh.write(\"This is my test file for exception handling!!\")\n", + "except IOError:\n", + " print (\"Error: can\\'t find file or read data\")\n", + "else:\n", + " print (\"Written content in the file successfully\")\n", + " fh.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:23.463799Z", + "start_time": "2021-06-18T15:57:21.649361Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter a number: 6\n", + "0.16666666666666666\n" + ] + } + ], + "source": [ + "# Example 2: program to print the reciprocal of even numbers\n", + "\n", + "try:\n", + " num = int(input(\"Enter a number: \"))\n", + " assert num % 2 == 0\n", + "except:\n", + " print(\"Not an even number!\")\n", + "else:\n", + " reciprocal = 1/num\n", + " print(reciprocal)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Explanation**:\n", + "\n", + "If we pass an odd number:\n", + "\n", + "```python\n", + "Enter a number: 1\n", + "Not an even number!\n", + "```\n", + "\n", + "If we pass an even number, the reciprocal is computed and displayed.\n", + "\n", + "```python\n", + "Enter a number: 4\n", + "0.25\n", + "```\n", + "\n", + "However, if we pass 0, we get **`ZeroDivisionError`** as the code block inside else is not handled by preceding except.\n", + "\n", + "```python\n", + "Enter a number: 0\n", + "Traceback (most recent call last):\n", + " File \"\", line 7, in \n", + " reciprocal = 1/num\n", + "ZeroDivisionError: division by zero\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The `except` Clause with No Exceptions\n", + "\n", + "You can also use the except statement with no exceptions defined as follows\n", + "\n", + "```python\n", + ">>> try:\n", + ">>> You do your operations here\n", + ">>> ......................\n", + ">>> except:\n", + ">>> If there is any exception, then execute this block.\n", + ">>> ......................\n", + ">>> else:\n", + ">>> If there is no exception then execute this block\n", + "```\n", + "\n", + "This kind of a **try-except** statement catches all the exceptions that occur. Using this kind of try-except statement is not considered a good programming practice though, because it catches all exceptions but does not make the programmer identify the root cause of the problem that may occur." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The `except` Clause with Multiple Exceptions\n", + "\n", + "You can also use the same except statement to handle multiple exceptions as follows −\n", + "\n", + "```python\n", + ">>>try:\n", + ">>> You do your operations here\n", + ">>> ......................\n", + ">>>except(Exception1[, Exception2[,...ExceptionN]]]):\n", + ">>> If there is any exception from the given exception list,\n", + ">>> then execute this block.\n", + ">>> ......................\n", + ">>>else:\n", + ">>> If there is no exception then execute this block.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Python `try`-`finally` Clause\n", + "\n", + "The **`try`** statement in Python can have an optional **`finally`** clause. This clause is executed no matter what, and is generally used to release external resources.\n", + "\n", + "For example, we may be connected to a remote data center through the network or working with a file or a Graphical User Interface (GUI).\n", + "\n", + "In all these circumstances, we must clean up the resource before the program comes to a halt whether it successfully ran or not. These actions (closing a file, GUI or disconnecting from network) are performed in the **`finally`** clause to guarantee the execution.\n", + "\n", + "You can use a **finally: block** along with a try: block. The finally: block is a place to put any code that must execute, whether the **try-block** raised an exception or not. The syntax of the **try-finally** statement is this −\n", + "\n", + "```python\n", + ">>> try:\n", + ">>> You do your operations here;\n", + ">>> ......................\n", + ">>> Due to any exception, this may be skipped.\n", + ">>> finally:\n", + ">>> This would always be executed.\n", + ">>> ......................\n", + "```\n", + "\n", + ">**Note**: You can provide except clause(s), or a finally clause, but not both. You cannot use else clause as well along with a **finally clause**." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:30.634157Z", + "start_time": "2021-06-18T15:57:30.616581Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error: can't find file or read data\n" + ] + } + ], + "source": [ + "try:\n", + " fh = open(\"testfile.txt\", \"w\")\n", + " fh.write(\"This is my test file for exception handling!!\")\n", + "finally:\n", + " print (\"Error: can\\'t find file or read data\")\n", + " fh.close()\n", + " \n", + "# If you do not have permission to open the file in writing mode, \n", + "# then this will produce the following result −" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is an example of **[file operations](https://github.com/milaan9/05_Python_Files/blob/main/001_Python_File_Input_Output.ipynb)** to illustrate this." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:35.822107Z", + "start_time": "2021-06-18T15:57:35.800627Z" + } + }, + "outputs": [], + "source": [ + "try:\n", + " f = open(\"testfile.txt\",encoding = 'utf-8')\n", + " # perform file operations\n", + "finally:\n", + " f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Explanation**:\n", + "\n", + "This type of construct makes sure that the file is closed even if an exception occurs during the program execution." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Argument of an Exception\n", + "\n", + "An exception can have an **argument**, which is a value that gives additional information about the problem. The contents of the argument vary by exception. You capture an exception's argument by supplying a variable in the except clause as follows −" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:42.041302Z", + "start_time": "2021-06-18T15:57:42.025681Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The argument does not contain numbers\n", + " invalid literal for int() with base 10: 'xyz'\n" + ] + } + ], + "source": [ + "# Define a function here.\n", + "def temp_convert(var):\n", + " try:\n", + " return int(var)\n", + " except ValueError as Argument:\n", + " print (\"The argument does not contain numbers\\n\", Argument)\n", + "\n", + "# Call above function here.\n", + "temp_convert(\"xyz\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Raising an Exception\n", + "\n", + "You can raise exceptions in several ways by using the **`raise`** statement. \n", + "\n", + "The general syntax for the **`raise`** statement is as follows:\n", + "\n", + "```python\n", + "raise [Exception [, args [, traceback]]]\n", + "```\n", + "\n", + "Here, Exception is the type of exception (for example, **NameError**) and argument is a value for the exception argument. The argument is optional; if not supplied, the exception argument is None.\n", + "\n", + "The final argument, traceback, is also optional (and rarely used in practice), and if present, is the traceback object used for the exception." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T15:57:46.716562Z", + "start_time": "2021-06-18T15:57:46.697036Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "error in level argument -10\n" + ] + } + ], + "source": [ + "def functionName( level ):\n", + " if level < 1:\n", + " raise Exception(level)\n", + " # The code below to this would not be executed\n", + " # if we raise the exception\n", + " return level\n", + "\n", + "try:\n", + " l = functionName(-10)\n", + " print (\"level = \",l)\n", + "except Exception as e:\n", + " print (\"error in level argument\",e.args[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Writing the “Hello, World!” Program\n", + "\n", + "Python also allows you to create your own exceptions by deriving classes from the standard **built-in exceptions**.\n", + "\n", + "Here is an example related to **RuntimeError**. Here, a class is created that is subclassed from RuntimeError. This is useful when you need to display more **specific information** when an exception is caught.\n", + "\n", + "In the try block, the user-defined exception is raised and caught in the except block. The variable e is used to create an instance of the class **Networkerror**.\n", + "\n", + "```python\n", + ">>> class Networkerror(RuntimeError):\n", + ">>> def _init_(self, arg):\n", + ">>> self.args = arg\n", + "```\n", + " \n", + "So once you have defined the above class, you can raise the exception as follows −\n", + "\n", + "```python\n", + ">>> try:\n", + ">>> raise Networkerror(\"Bad hostname\")\n", + ">>> except Networkerror,e:\n", + ">>> print(e.args)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/005_Python_User_defined_Exceptions.ipynb b/005_Python_User_defined_Exceptions.ipynb new file mode 100644 index 0000000..895b8a3 --- /dev/null +++ b/005_Python_User_defined_Exceptions.ipynb @@ -0,0 +1,464 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/05_Python_Files)**\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Custom Exceptions\n", + "\n", + "In this class, you will learn how to define custom exceptions depending upon your requirements with the help of examples.\n", + "\n", + "Python has numerous **[built-in exceptions](https://github.com/milaan9/05_Python_Files/blob/main/003_Python_File_Exception.ipynb)** that force your program to output an error when something in the program goes wrong.\n", + "\n", + "However, sometimes you may need to create your own custom exceptions that serve your purpose." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Custom Exceptions\n", + "\n", + "In Python, users can define custom exceptions by creating a new class. This exception class has to be derived, either directly or indirectly, from the built-in **`Exception`** class. Most of the built-in exceptions are also derived from this class." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:19:27.045590Z", + "start_time": "2021-06-18T17:19:27.028011Z" + } + }, + "outputs": [], + "source": [ + "class CustomError(Exception):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:19:28.105637Z", + "start_time": "2021-06-18T17:19:27.828299Z" + } + }, + "outputs": [ + { + "ename": "CustomError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mCustomError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mCustomError\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mCustomError\u001b[0m: " + ] + } + ], + "source": [ + "raise CustomError" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:19:28.901530Z", + "start_time": "2021-06-18T17:19:28.883955Z" + } + }, + "outputs": [ + { + "ename": "CustomError", + "evalue": "An error occurred", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mCustomError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mCustomError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"An error occurred\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mCustomError\u001b[0m: An error occurred" + ] + } + ], + "source": [ + "raise CustomError(\"An error occurred\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, we have created a user-defined exception called **`CustomError`** which inherits from the **`Exception`** class. This new exception, like other exceptions, can be raised using the **`raise`** statement with an optional error message.\n", + "\n", + "When we are developing a large Python program, it is a good practice to place all the user-defined exceptions that our program raises in a separate file. Many standard modules do this. They define their exceptions separately as **`exceptions.py`** or **`errors.py`** (generally but not always).\n", + "\n", + "User-defined exception class can implement everything a normal class can do, but we generally make them simple and concise. Most implementations declare a custom base class and derive others exception classes from this base class. This concept is made clearer in the following example." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example: User-Defined Exception in Python\n", + "\n", + "In this example, we will illustrate how user-defined exceptions can be used in a program to raise and catch errors.\n", + "\n", + "This program will ask the user to enter a number until they guess a stored number correctly. To help them figure it out, a hint is provided whether their guess is greater than or less than the stored number." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:19:35.140743Z", + "start_time": "2021-06-18T17:19:31.339989Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter a number: 9\n", + "This value is too small, try again!\n", + "\n", + "Enter a number: 10\n", + "Congratulations! You guessed it correctly.\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\n**Output**:\\n\\nEnter a number: 12\\nThis value is too large, try again!\\n\\nEnter a number: 0\\nThis value is too small, try again!\\n\\nEnter a number: 8\\nThis value is too small, try again!\\n\\nEnter a number: 10\\nCongratulations! You guessed it correctly.\\n'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# define Python user-defined exceptions\n", + "class Error(Exception):\n", + " \"\"\"Base class for other exceptions\"\"\"\n", + " pass\n", + "\n", + "\n", + "class ValueTooSmallError(Error):\n", + " \"\"\"Raised when the input value is too small\"\"\"\n", + " pass\n", + "\n", + "\n", + "class ValueTooLargeError(Error):\n", + " \"\"\"Raised when the input value is too large\"\"\"\n", + " pass\n", + "\n", + "\n", + "# you need to guess this number\n", + "number = 10\n", + "\n", + "# user guesses a number until he/she gets it right\n", + "while True:\n", + " try:\n", + " i_num = int(input(\"Enter a number: \"))\n", + " if i_num < number:\n", + " raise ValueTooSmallError\n", + " elif i_num > number:\n", + " raise ValueTooLargeError\n", + " break\n", + " except ValueTooSmallError:\n", + " print(\"This value is too small, try again!\")\n", + " print()\n", + " except ValueTooLargeError:\n", + " print(\"This value is too large, try again!\")\n", + " print()\n", + "\n", + "print(\"Congratulations! You guessed it correctly.\")\n", + "\n", + "\n", + "'''\n", + "**Output**:\n", + "\n", + "Enter a number: 12\n", + "This value is too large, try again!\n", + "\n", + "Enter a number: 0\n", + "This value is too small, try again!\n", + "\n", + "Enter a number: 8\n", + "This value is too small, try again!\n", + "\n", + "Enter a number: 10\n", + "Congratulations! You guessed it correctly.\n", + "'''" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Explanation**:\n", + "\n", + "We have defined a base class called **`Error`**.\n", + "\n", + "The other two exceptions (**`ValueTooSmallError`** and **`ValueTooLargeError`**) that are actually raised by our program are derived from this class. This is the standard way to define user-defined exceptions in Python programming, but you are not limited to this way only." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Customizing Exception Classes\n", + "\n", + "We can further customize this class to accept other arguments as per our needs.\n", + "\n", + "To learn about customizing the Exception classes, you need to have the basic knowledge of **[Python Object-Oriented programming](https://github.com/milaan9/06_Python_Object_Class/blob/main/001_Python_OOPs_Concepts.ipynb)**.\n", + "\n", + "For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:19:44.198773Z", + "start_time": "2021-06-18T17:19:39.516192Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter salary amount: 3000\n" + ] + }, + { + "ename": "SalaryNotInRangeError", + "evalue": "Salary is not in (5000, 15000) range", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mSalaryNotInRangeError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[0msalary\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0minput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Enter salary amount: \"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;36m5000\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0msalary\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m15000\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mSalaryNotInRangeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msalary\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 18\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m '''\n", + "\u001b[1;31mSalaryNotInRangeError\u001b[0m: Salary is not in (5000, 15000) range" + ] + } + ], + "source": [ + "class SalaryNotInRangeError(Exception):\n", + " \"\"\"Exception raised for errors in the input salary.\n", + "\n", + " Attributes:\n", + " salary -- input salary which caused the error\n", + " message -- explanation of the error\n", + " \"\"\"\n", + "\n", + " def __init__(self, salary, message=\"Salary is not in (5000, 15000) range\"):\n", + " self.salary = salary\n", + " self.message = message\n", + " super().__init__(self.message)\n", + "\n", + "\n", + "salary = int(input(\"Enter salary amount: \"))\n", + "if not 5000 < salary < 15000:\n", + " raise SalaryNotInRangeError(salary)\n", + " \n", + "'''\n", + "**Output**:\n", + "\n", + "Enter salary amount: 3000\n", + "\n", + "SalaryNotInRangeError Traceback (most recent call last)\n", + " in \n", + " 15 salary = int(input(\"Enter salary amount: \"))\n", + " 16 if not 5000 < salary < 15000:\n", + "---> 17 raise SalaryNotInRangeError(salary)\n", + "\n", + "SalaryNotInRangeError: Salary is not in (5000, 15000) range\n", + "'''" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Explanation:**\n", + "\n", + "Here, we have overridden the constructor of the **`Exception`** class to accept our own custom arguments **`salary`** and **`message`**. Then, the constructor of the parent **`Exception`** class is called manually with the **`self.message`** argument using **`super()`**.\n", + "\n", + "The custom **`self.salary`** attribute is defined to be used later.\n", + "\n", + "The inherited **`__str__`** method of the **`Exception`** class is then used to display the corresponding message when **`SalaryNotInRangeError`** is raised." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also customize the **`__str__`** method itself by overriding it." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2021-06-18T17:20:11.265939Z", + "start_time": "2021-06-18T17:20:08.927580Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter salary amount: 3000\n" + ] + }, + { + "ename": "SalaryNotInRangeError", + "evalue": "3000 -> Salary is not in (5000, 15000) range", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mSalaryNotInRangeError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 18\u001b[0m \u001b[0msalary\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0minput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Enter salary amount: \"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;36m5000\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0msalary\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m15000\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 20\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mSalaryNotInRangeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msalary\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 21\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m '''\n", + "\u001b[1;31mSalaryNotInRangeError\u001b[0m: 3000 -> Salary is not in (5000, 15000) range" + ] + } + ], + "source": [ + "class SalaryNotInRangeError(Exception):\n", + " \"\"\"Exception raised for errors in the input salary.\n", + "\n", + " Attributes:\n", + " salary -- input salary which caused the error\n", + " message -- explanation of the error\n", + " \"\"\"\n", + "\n", + " def __init__(self, salary, message=\"Salary is not in (5000, 15000) range\"):\n", + " self.salary = salary\n", + " self.message = message\n", + " super().__init__(self.message)\n", + "\n", + " def __str__(self):\n", + " return f'{self.salary} -> {self.message}'\n", + "\n", + "\n", + "salary = int(input(\"Enter salary amount: \"))\n", + "if not 5000 < salary < 15000:\n", + " raise SalaryNotInRangeError(salary)\n", + " \n", + "'''\n", + "**Output**:\n", + "\n", + "Enter salary amount: 3000\n", + "\n", + "SalaryNotInRangeError Traceback (most recent call last)\n", + " in \n", + " 18 salary = int(input(\"Enter salary amount: \"))\n", + " 19 if not 5000 < salary < 15000:\n", + "---> 20 raise SalaryNotInRangeError(salary)\n", + "\n", + "SalaryNotInRangeError: 3000 -> Salary is not in (5000, 15000) range\n", + "'''" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To learn more about how you can handle exceptions in Python, visit **[Python Exception Handling](https://github.com/milaan9/05_Python_Files/blob/main/004_Python_Exceptions_Handling.ipynb)**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}