{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "21df53b0",
   "metadata": {},
   "source": [
    "## More Python modules\n",
    "\n",
    "- ```configparser``` - reads config parameters from INI file into dictionary.\n",
    "- ```json``` - reads/writes jason files, encodes/decodes python object into json.\n",
    "- ```gzip``` - compresses/decompresses binary data, reads/writes data into *.gzip file.\n",
    "- ```zipfile``` - creates, adds, reads, writes to zip archives.\n",
    "- ```getpass``` - reads password from keyboard.\n",
    "- ```glob``` - finds files with matched regexp patterns.\n",
    "- ```pathlib``` - object-oriented approach to handling filesystem paths.\n",
    "- ```argparse``` - passes parameters to a python script.\n",
    "- Exception handling."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cd246dd-8478-4279-9a6e-0650c8f1652f",
   "metadata": {},
   "source": [
    "***\n",
    "### Module configparser (Exercise)\n",
    "\n",
    "The module is utilized to read configuration from INI file into Python dictionary.\n",
    "\n",
    "In directory Python, create file ```services.ini```  with the following content:\n",
    "```ini\n",
    "[New York]\n",
    "dns = 192.168.3.250\n",
    "dhcp = 192.168.3.250\n",
    "ldapmaster = 192.168.3.100\n",
    "ldap = 192.168.3.100\n",
    "db = 192.168.11.104\n",
    "\n",
    "[Chicago]\n",
    "dns = 192.168.11.104\n",
    "dhcp = 192.168.11.104\n",
    "ldapmaster = 192.168.11.100\n",
    "ldap = 192.168.11.100\n",
    "db = 192.168.11.100\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad371b33-dda8-492e-89e1-e1d16e30751c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import configparser\n",
    "\n",
    "# Initialize the parser\n",
    "config = configparser.ConfigParser()\n",
    "\n",
    "# Read the file into the parser\n",
    "config.read('services.ini')\n",
    "\n",
    "for key, value in config['Chicago'].items():\n",
    "        print(f\"Server {key} IP: {value}\")\n",
    "\n",
    "for key, value in config['New York'].items():\n",
    "        print(f\"Server {key} IP: {value}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2add2119-e81a-4200-9e8e-1fa9aee31e39",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Read dictionary config into parser\n",
    "config.read_dict(config)\n",
    "\n",
    "# Write the parser's contents to an INI file\n",
    "with open('config.ini', 'w') as configfile:\n",
    "    config.write(configfile)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b467631",
   "metadata": {},
   "source": [
    "***\n",
    "### JSON  (Exercise)\n",
    "\n",
    "JSON is JavaScript Object Notation. It is used to store and transfer data. \n",
    "\n",
    "- json.load() reads data from json file\n",
    "- jason.dump() writes data in json file\n",
    "- json.dumps() encodes a python object (usually dictionary) into json\n",
    "- json.loads() decodes json into python object\n",
    "\n",
    "Create file ```services.json``` in directory Python with the following content:\n",
    "\n",
    "```json\n",
    "{\n",
    "    \"New York\": {\n",
    "        \"dns\": [\n",
    "            \"192.168.3.250\",\n",
    "            \"192.168.11.104\"\n",
    "        ],\n",
    "        \"dhcp\": \"192.168.3.250\",\n",
    "        \"ldapmaster\": \"192.168.3.100\",\n",
    "        \"ldap\": [\n",
    "            \"192.168.3.100\",\n",
    "            \"192.168.11.104\"\n",
    "        ],\n",
    "        \"db\": \"192.168.3.40\"\n",
    "    },\n",
    "    \"Chicago\": {\n",
    "        \"dns\": [\n",
    "            \"192.168.11.104\",\n",
    "            \"192.168.3.250\"\n",
    "        ],\n",
    "        \"dhcp\": \"192.168.11.104\",\n",
    "        \"ldapmaster\": \"192.168.3.100\",\n",
    "        \"ldap\": \"[192.168.11.104, 192.168.3.100]\",\n",
    "        \"db\": \"192.168.11.100\"\n",
    "    }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4895927-817e-4923-85fe-a48a2be7f190",
   "metadata": {},
   "source": [
    "#### Read data from json file:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "395be6c7-7d5a-4e15-b7d2-bd4b7f7f2344",
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "with open('services.json','r') as f:\n",
    "    data= json.load(f)\n",
    "\n",
    "for key, value in data['New York'].items():\n",
    "    print(f\"Server {key} IP: {value}\")\n",
    "\n",
    "for key, value in data['Chicago'].items():\n",
    "    print(f\"Server {key} IP: {value}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25d77875-56a1-427b-a55a-a75758730afc",
   "metadata": {},
   "source": [
    "#### Dump data into a json file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc2a4ff4-c4e7-433f-9377-879c79bf823d",
   "metadata": {},
   "outputs": [],
   "source": [
    "with  open(\"services2.json\", \"w\") as out_file:\n",
    "    json.dump(data, out_file, indent = 4) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84a02164-9b7d-4c5d-b510-2f2448a6fbc0",
   "metadata": {},
   "source": [
    "#### Encode a dictionary into a json string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "755e306d-a466-45c0-8426-90f303867290",
   "metadata": {},
   "outputs": [],
   "source": [
    "json_string = json.dumps(services)\n",
    "print(json_string)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb528b31-b2aa-4776-abca-1c62a8ffc4f8",
   "metadata": {},
   "source": [
    "#### Decode json string into a dictionary:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "840786fe-5b8b-4166-bf76-e3c2b8cbe204",
   "metadata": {},
   "outputs": [],
   "source": [
    "dict = json.loads(json_string)\n",
    "print(dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cb7d85e",
   "metadata": {},
   "source": [
    "***\n",
    "### Module gzip (Exercise)\n",
    "\n",
    "\n",
    "The module is utilized to\n",
    "\n",
    "- compress/decompress binary data\n",
    "- write data into compressed *.gz file\n",
    "- read data from compressed *.gz file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "83d38686",
   "metadata": {},
   "outputs": [],
   "source": [
    "## See all the methods in the module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45b7b54c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import gzip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8ab6d14c",
   "metadata": {},
   "outputs": [],
   "source": [
    "data = '''\n",
    " Create some data. \\nIn this particular case, \\nthe data is just two sentences stored in a string\\n \n",
    " Line 4 \\n\n",
    " Line 5 \\n\n",
    " Line 6 \\n \n",
    " Line 7\n",
    " '''\n",
    "\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1a9be74",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Store data into gzip file, data.txt.gz.  The procedure is very similar to writing data into a regular file. \n",
    "## Notice the write option 'wt' is for writing text:\n",
    "\n",
    "with gzip.open(\"data.txt.gz\",\"wt\") as f:\n",
    "    f.write(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5619a0e",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Check if file data.txt.gz shows up in the directory:\n",
    "\n",
    "import os\n",
    "os.listdir()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "760f3f09",
   "metadata": {},
   "outputs": [],
   "source": [
    "%ls data.txt.gz\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c94d27d",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Let's check if we can read data back from the file. Notice the read option 'rt' is for reading text:\n",
    "\n",
    "with gzip.open(\"data.txt.gz\",\"rt\") as f:\n",
    "    data_read = f.read()\n",
    "    \n",
    "print(data_read)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5371d94",
   "metadata": {},
   "outputs": [],
   "source": [
    "## We cal also convert the data into a binary form, then write it into gzip file with 'wb' option"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1802c8c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "#data_byte = bytes(data, 'utf-8')\n",
    "data_byte = data.encode('utf-8')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96ef849f",
   "metadata": {},
   "outputs": [],
   "source": [
    "type(data_byte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0340e9a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(data_byte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "281a73c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Store the binary data into gzip file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1e2842c",
   "metadata": {},
   "outputs": [],
   "source": [
    "with gzip.open(\"data.txt.gz\",\"wb\") as f:\n",
    "    f.write(data_byte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9ad51bb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37555e80",
   "metadata": {},
   "outputs": [],
   "source": [
    "## This also can be done with GzipFile method:\n",
    "with gzip.GzipFile(\"data.txt.gz\",\"wb\") as f:\n",
    "    f.write(data_byte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2891b9f5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "34ed3ed5",
   "metadata": {},
   "outputs": [],
   "source": [
    "## We can also read the gzip file into binary data type by using \"rb\" option:\n",
    "\n",
    "with gzip.open(\"data.txt.gz\",\"rb\") as f:\n",
    "    out_byte = f.read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f512b94d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(out_byte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9af5126",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Compressing/decompressing data. It can be applied to binary data only.\n",
    "## Check the sizes of text data, byte data, and compressed byte data:\n",
    "\n",
    "import sys\n",
    "\n",
    "size_txt = sys.getsizeof(data)\n",
    "\n",
    "out_byte = data.encode('utf-8')\n",
    "size_bin = sys.getsizeof(out_byte)\n",
    "\n",
    "out_compressed = gzip.compress(out_byte)\n",
    "size_compressed = sys.getsizeof(out_compressed)\n",
    "\n",
    "print(size_txt, '>', size_bin, '>', size_compressed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0a9ee00",
   "metadata": {},
   "source": [
    "***\n",
    "### Module zipfile (Exercise)\n",
    "\n",
    "Works with zip archives:\n",
    "\n",
    "- Reads list of files and directories from zip archive\n",
    "- Extracts files from an archive\n",
    "- Reads specific file from an archive\n",
    "- Creates a new archive\n",
    "- Adds/appends file to the archive"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ea19215",
   "metadata": {},
   "source": [
    "#### Download a zip file:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "82ddc823",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.system('wget --no-check-certificate https://linuxcourse.rutgers.edu/2024/html/files/test.zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0007a2b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import zipfile"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "619c6b05",
   "metadata": {},
   "outputs": [],
   "source": [
    "with zipfile.ZipFile('test.zip') as file:   \n",
    "    # printing all the information of archive file contents using 'printdir' method\n",
    "    print(file.printdir())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24f231d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "with zipfile.ZipFile('test.zip') as file:   \n",
    "    # ZipFile.namelist() returns a list containing all the members with names of an archive file\n",
    "    print(file.namelist())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c1077eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "with zipfile.ZipFile('test.zip') as file:\n",
    "    # Open and read the content of a file from the list:\n",
    "    with file.open(name = file.namelist()[1], mode = 'r') as text_file:\n",
    "        print(text_file.read().decode('utf-8'))  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d68cd841",
   "metadata": {},
   "outputs": [],
   "source": [
    " with zipfile.ZipFile('test.zip') as file:\n",
    "\n",
    "        # ZipFile.infolist() returns a list containing all the members of an archive file\n",
    "        print(file.infolist())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc5e8b54",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Extract the content of zip file into a new directory, EXTRACT_DIR\n",
    "\n",
    "\n",
    "with zipfile.ZipFile('test.zip') as f:\n",
    "        f.extractall('EXTRACT_DIR')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a439065",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.listdir('EXTRACT_DIR')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74a1e78d",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Create an empty zipfile:\n",
    "\n",
    "archive_name = 'new_test.zip'\n",
    "f = zipfile.ZipFile(archive_name, 'w')\n",
    "f.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd8203b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Add a new file, /etc/hosts, to the existing archive. Ovewrite existing files there.\n",
    "with zipfile.ZipFile('new_test.zip', 'w') as f:\n",
    "        f.write('/etc/hosts')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "32637ec7",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Append a new file, /etc/passwd. This doesn't overwrite the existing files.\n",
    "with zipfile.ZipFile('new_test.zip', 'a') as f:\n",
    "        f.write('/etc/passwd')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe56c934",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Check the content of archive new_test.zip\n",
    "with zipfile.ZipFile('new_test.zip','r') as f:\n",
    "    print(f.printdir())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1683608f",
   "metadata": {},
   "source": [
    "***\n",
    "### Module getpass (Exercise)\n",
    "\n",
    "- Promps for password and reads it from stdin\n",
    "- Figures out the user name from the environment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "866e7ecb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import getpass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2ed6b23",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Prompt for password and read user password:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2c95695",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = getpass.getpass(prompt='Enter the password: ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db53ffc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "if p == 'this':\n",
    "    print('correct password')\n",
    "else:\n",
    "    print('password incorrect')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "370b26b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "## identify the user and prompt in the loop until success. Maximum 10 attempts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "67225af7",
   "metadata": {},
   "outputs": [],
   "source": [
    "user = getpass.getuser()\n",
    "\n",
    "count = 0\n",
    "max_count = 10\n",
    "\n",
    "#while True:  \n",
    "while count <= max_count:\n",
    "    \n",
    "    pwd = getpass.getpass(\"User Name : %s\" % user)\n",
    "    \n",
    "    count += 1\n",
    "\n",
    "    if pwd == 'password1':\n",
    "        print(\"login successful\")\n",
    "        break\n",
    "    else:\n",
    "        print(\"The password you entered is incorrect.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5eb69d8",
   "metadata": {},
   "source": [
    "***\n",
    "### Module glob (Exercise)\n",
    "\n",
    "- Finds files matching a specified pattern and\n",
    "  returns them in a list [ ]\n",
    "- `*` matches zero or more characters\n",
    "- `?` matches one character\n",
    "- [0-9] matches any number\n",
    "- [a-z] matches any low case character\n",
    "- [A-Z] matches any upper case character"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e5c9cc38",
   "metadata": {},
   "outputs": [],
   "source": [
    "import glob"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed59ddfc",
   "metadata": {},
   "outputs": [],
   "source": [
    "glob.glob('*.zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2752d8d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "glob.glob('*[0-9].zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c318926",
   "metadata": {},
   "outputs": [],
   "source": [
    "glob.glob('*[a-z].zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3fcf4405",
   "metadata": {},
   "outputs": [],
   "source": [
    "glob.glob('[A-Z]*[0-9].zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1d8fc3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "glob.glob('[n,I]e*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7faa403",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Search for files specifically in /etc\n",
    "glob.glob('/etc/*.conf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "789bab20",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Search for files in directory and subdirectories /etc\n",
    "glob.glob('/etc/*/*.conf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "627e5f17",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Recursive search in a directory tree\n",
    "glob.glob('/etc/**/*.conf', recursive=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "758a975d",
   "metadata": {},
   "outputs": [],
   "source": [
    "## For recursive search, it is better using iterative method `iglob` to save space in RAM. \n",
    "## The iglob runs iteratively so doesn't buffer the output unlike glob.\n",
    "\n",
    "for filename in glob.iglob('/etc/**/*.conf', recursive=True):\n",
    "    print(filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70d68fea-c26e-494f-b7f8-2fbdb82aad8e",
   "metadata": {},
   "source": [
    "***\n",
    "### Module pathlib (Exercise) \n",
    "\n",
    "The module provides an object-oriented approach to handling filesystem paths. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "915f3047-2ca0-4d31-9fda-0217b6445744",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb2f5830-e1e7-43d4-8acd-9cfcec209ca9",
   "metadata": {},
   "outputs": [],
   "source": [
    "Path.home()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "740a6f6a-7159-4921-b5cc-3d1d75f5cd01",
   "metadata": {},
   "source": [
    "Create a new directory, ```/home/hostadm/Python2```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "edd8d45b-a9d4-43b3-a9fb-7e3010249407",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Path.home() / 'Python2'\n",
    "p.mkdir()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62ade510-648d-4de0-b80a-04e0838ab169",
   "metadata": {},
   "source": [
    "Create a new file in the directory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88624ccd-55b1-47ab-bc60-3c0adce1dd58",
   "metadata": {},
   "outputs": [],
   "source": [
    "nf = p / 'new_file.txt'\n",
    "nf\n",
    "nf.touch()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a94c192e-bea4-43ae-8adb-91b172fe7710",
   "metadata": {},
   "source": [
    "Check if the directory and the file exist:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7928da26-6c13-4162-8661-2fc8b803f750",
   "metadata": {},
   "outputs": [],
   "source": [
    "nf.is_file()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf35ebb1-444f-4d9d-9343-a637b555f142",
   "metadata": {},
   "outputs": [],
   "source": [
    "p.is_dir()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46cf4804-9330-4ba1-b131-738bf7da841a",
   "metadata": {},
   "source": [
    "Rename the file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "67d0307d-637d-4db0-93a2-37bff28a73a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "nfn = p / 'new_file2.txt'\n",
    "\n",
    "nf.rename(nfn)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "402949ea-43b7-406c-8f05-42366e957394",
   "metadata": {},
   "source": [
    "Write data into file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e418c50c-ba71-4fe9-9af0-f2b023cecc2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "nf.write_text(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8911b265-9ea2-4b92-b71d-fbcbc4ed4d1a",
   "metadata": {},
   "source": [
    "Read text from data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6ad83c3-3d3a-4cb6-b56e-d3a450b21a8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "s = Path('/home/hostadm/Python2/new_file.txt').read_text()\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67b7e150-7cea-4e6c-9638-148b651fd0b9",
   "metadata": {},
   "source": [
    "List files in the directory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d0f9818-d92c-4475-8642-19825d43dada",
   "metadata": {},
   "outputs": [],
   "source": [
    "s = [ s.name for s in list(p.glob('*'))]\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96708569",
   "metadata": {},
   "source": [
    "***\n",
    "### Exception handling in Python (Exercise)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e6f34ed-05c9-4857-8c31-15c9ccca746c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "beac1c4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Example: find all conf files that contain keyword `network`.\n",
    "## This will throw an error since some files in /etc are not readable by the user.\n",
    "\n",
    "for filename in glob.iglob('/etc/**/*.conf', recursive=True):\n",
    "    with open(filename) as f:\n",
    "        line = f.read()\n",
    "        if 'network' in line:\n",
    "            print(filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3908e45e",
   "metadata": {},
   "source": [
    "To allow the script to run and prompt us about errors, we run it within block\n",
    "```python\n",
    "try:\n",
    "...\n",
    "except ...\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "473502d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "## Lets handle the exception above\n",
    "for filename in glob.iglob('/etc/**/*.conf', recursive=True):\n",
    "    try:\n",
    "        with open(filename) as f:\n",
    "            line = f.read()\n",
    "            if 'network' in line:\n",
    "                print(filename)\n",
    "                \n",
    "    except PermissionError as e:\n",
    "            print(f\"can't read {filename}: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d836f232",
   "metadata": {},
   "source": [
    "There is another, ```FileNotFoundError```, error due to a symbolic link to a missing file.\n",
    "\n",
    "We can handle multipple exceptions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dbdad043",
   "metadata": {},
   "outputs": [],
   "source": [
    "for filename in glob.iglob('/etc/**/*.conf', recursive=True):\n",
    "    try:\n",
    "        with open(filename) as f:\n",
    "            line = f.read()\n",
    "            if 'network' in line:\n",
    "                print(filename)\n",
    "                \n",
    "    except (PermissionError, FileNotFoundError) as e:\n",
    "            print(f\"can't read {filename}: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "530d8a90",
   "metadata": {},
   "source": [
    "The last two exceptions we can catch with a generic  ```OSError```:\n",
    "```python\n",
    "except OSError as e:\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdef3816",
   "metadata": {},
   "source": [
    "In numerical computations, you may need to deal with the division by zero. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b01431e",
   "metadata": {},
   "outputs": [],
   "source": [
    "denominator = [1.2, 4.0, 0.001, 45.0, 0.0]\n",
    "\n",
    "numerator = 0.1\n",
    "\n",
    "for i in denominator:\n",
    "    s = numerator / i\n",
    "    print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4141532",
   "metadata": {},
   "source": [
    "We need to put safe guards with \n",
    "```python\n",
    "except ZeroDivisionError as e:\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95eca0cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    for i in denominator:\n",
    "      s = numerator / i\n",
    "      print(s)\n",
    "\n",
    "except ZeroDivisionError  as e:\n",
    "    print('Division by zero, i = ', i)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7c23586",
   "metadata": {},
   "source": [
    "### Parsing arguments with argparse (Exercise)\n",
    "\n",
    "It allows to pass parameters to a python script.\n",
    "\n",
    "All the exercises below should run in the Linux command prompt.\n",
    "There are 3 python scripts in the directory: parser_1.py, parser_2.py, and parser_3.py\n",
    "\n",
    "\n",
    "Exersizes:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c071176",
   "metadata": {},
   "source": [
    "```bash\n",
    "# Import the library\n",
    "import argparse\n",
    "# Create the parser\n",
    "parser = argparse.ArgumentParser()\n",
    "# Add an argument\n",
    "parser.add_argument('--alpha', type=int, required=True)\n",
    "# Parse the argument\n",
    "args = parser.parse_args()\n",
    "\n",
    "# use and print the argument\n",
    "value = args.alpha * 10\n",
    "print('alpha = ', args.alpha, f', value = {args.alpha} * 10 = ', value)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5921bb9",
   "metadata": {},
   "source": [
    "#### Run the script\n",
    "\n",
    "Save the above cell in a script, say parser_1.py, specify that it is a python script in the header:\n",
    "```bash\n",
    "#!/home/hostadm/miniconda3/bin/python3\n",
    "```\n",
    "\n",
    "Make it executable:\n",
    "```bash\n",
    "chmod a+x parser_1.py\n",
    "```\n",
    "\n",
    "Run the script with the parameter:\n",
    "```bash\n",
    "./parser_1.py --alpha 15\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06bd71d8",
   "metadata": {},
   "source": [
    "#### Multiple arguments with help options"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34659ec3",
   "metadata": {},
   "source": [
    "```bash\n",
    "import argparse\n",
    "parser = argparse.ArgumentParser()\n",
    "\n",
    "parser.add_argument('--a1', type = str, required=True, help = 'First coefficient')\n",
    "parser.add_argument('--a2', type = str, required=True, help = 'Second coefficient')\n",
    "parser.add_argument('--a3', type = str, help = 'Third coefficient')\n",
    "\n",
    "args = parser.parse_args()\n",
    "\n",
    "s = f'{args.a1}*x^2 + {args.a2}*x + {args.a2}'\n",
    "\n",
    "print(s)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f81d008c",
   "metadata": {},
   "source": [
    "#### Invoking help\n",
    "\n",
    "Save the content of the cell above in file, say, parser_2.py, then run as follows:\n",
    "\n",
    "```bash\n",
    "./parser_2.py -h\n",
    "./parser_2.py  --a1 34 --a2 55 --a3 56\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80cc7d46",
   "metadata": {},
   "source": [
    "#### Multiple arguments of the same type\n",
    "\n",
    "```bash\n",
    "import argparse\n",
    "parser = argparse.ArgumentParser()\n",
    "\n",
    "parser.add_argument('--values', type=int, nargs=3)\n",
    "\n",
    "args = parser.parse_args()\n",
    "sum = sum(args.values)\n",
    "print('Sum:', sum)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "227541f2",
   "metadata": {},
   "source": [
    "Run it with values:\n",
    "\n",
    "```bash\n",
    "./parser_3.py --values 4 8 9\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "362d5c58",
   "metadata": {},
   "source": [
    "For any number of values, set ```nargs = '+'```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df4de3be",
   "metadata": {},
   "source": [
    "### Reference\n",
    "\n",
    "[Good tutorial on subparsers](https://towardsdatascience.com/a-simple-guide-to-command-line-arguments-with-argparse-6824c30ab1c3)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.13.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
