From e7efc6396df6a5a0bfbccdb4655abf8ded04fc1d Mon Sep 17 00:00:00 2001 From: abhishekrahul93 Date: Sun, 15 Feb 2026 12:35:18 +0100 Subject: [PATCH] Solved lab --- .ipynb_checkpoints/README-checkpoint.md | 92 ++++++ .../python sql-checkpoint.ipynb | 310 ++++++++++++++++++ python sql.ipynb | 310 ++++++++++++++++++ 3 files changed, 712 insertions(+) create mode 100644 .ipynb_checkpoints/README-checkpoint.md create mode 100644 .ipynb_checkpoints/python sql-checkpoint.ipynb create mode 100644 python sql.ipynb diff --git a/.ipynb_checkpoints/README-checkpoint.md b/.ipynb_checkpoints/README-checkpoint.md new file mode 100644 index 0000000..b0ef389 --- /dev/null +++ b/.ipynb_checkpoints/README-checkpoint.md @@ -0,0 +1,92 @@ +![logo_ironhack_blue 7](https://user-images.githubusercontent.com/23629340/40541063-a07a0a8a-601a-11e8-91b5-2f13e4e6b441.png) + +# LAB | Connecting Python to SQL + +
+ +

Learning Goals

+
+ + This lab allows you to practice and apply the concepts and techniques taught in class. + + Upon completion of this lab, you will be able to: + +- Write a Python script to connect to a relational database using the appropriate Python library and query it using SQL commands. + +
+
+ +
+ +
+ +

Prerequisites

+
+ +Before this starting this lab, you should have learnt about: + +- Basic SQL queries +- Python and Pandas +- Data Wrangling, which involves tasks such as grouping, aggregating, dealing with indexes, renaming columns, merging data and performing calculations. + +
+
+ +
+ + +## Introduction + +Welcome to the Connecting Python to SQL lab! + +In this lab, you will be working with the [Sakila](https://dev.mysql.com/doc/sakila/en/) database on movie rentals. Specifically, you will be practicing how to do basic SQL queries using Python. By connecting Python to SQL, you can leverage the power of both languages to efficiently manipulate and analyze large datasets. Throughout this lab, you will practice how to use Python to retrieve and manipulate data stored in the Sakila database using SQL queries. Let's get started! + +## Challenge + +In this lab, the objective is to identify the customers who were active in both May and June, and how did their activity differ between months. To achieve this, follow these steps: + +1. Establish a connection between Python and the Sakila database. + +2. Write a Python function called `rentals_month` that retrieves rental data for a given month and year (passed as parameters) from the Sakila database as a Pandas DataFrame. The function should take in three parameters: + + - `engine`: an object representing the database connection engine to be used to establish a connection to the Sakila database. + - `month`: an integer representing the month for which rental data is to be retrieved. + - `year`: an integer representing the year for which rental data is to be retrieved. + + The function should execute a SQL query to retrieve the rental data for the specified month and year from the rental table in the Sakila database, and return it as a pandas DataFrame. + +3. Develop a Python function called `rental_count_month` that takes the DataFrame provided by `rentals_month` as input along with the month and year and returns a new DataFrame containing the number of rentals made by each customer_id during the selected month and year. + + The function should also include the month and year as parameters and use them to name the new column according to the month and year, for example, if the input month is 05 and the year is 2005, the column name should be "rentals_05_2005". + + + *Hint: Consider making use of pandas [groupby()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html)* + +4. Create a Python function called `compare_rentals` that takes two DataFrames as input containing the number of rentals made by each customer in different months and years. +The function should return a combined DataFrame with a new 'difference' column, which is the difference between the number of rentals in the two months. + +## Requirements + +- Fork this repo +- Clone it to your machine + + + +## Getting Started + +Complete the challenges. Follow the instructions and add your code and explanations as necessary. + +## Submission + +- Upon completion, run the following commands: + +```bash +git add . +git commit -m "Solved lab" +git push origin master +``` + +- Paste the link of your lab in Student Portal. + + + diff --git a/.ipynb_checkpoints/python sql-checkpoint.ipynb b/.ipynb_checkpoints/python sql-checkpoint.ipynb new file mode 100644 index 0000000..4af63ac --- /dev/null +++ b/.ipynb_checkpoints/python sql-checkpoint.ipynb @@ -0,0 +1,310 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "abeedd4a-10ee-49fd-9edf-9825974e963b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connection established successfully!\n" + ] + }, + { + "ename": "OperationalError", + "evalue": "(pymysql.err.OperationalError) (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")\n(Background on this error at: https://sqlalche.me/e/20/e3q8)", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mConnectionRefusedError\u001b[39m Traceback (most recent call last)", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:661\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 660\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m sock = \u001b[43msocket\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcreate_connection\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 662\u001b[39m \u001b[43m \u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mhost\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mport\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect_timeout\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\n\u001b[32m 663\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 664\u001b[39m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\socket.py:864\u001b[39m, in \u001b[36mcreate_connection\u001b[39m\u001b[34m(address, timeout, source_address, all_errors)\u001b[39m\n\u001b[32m 863\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m all_errors:\n\u001b[32m--> \u001b[39m\u001b[32m864\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exceptions[\u001b[32m0\u001b[39m]\n\u001b[32m 865\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m ExceptionGroup(\u001b[33m\"\u001b[39m\u001b[33mcreate_connection failed\u001b[39m\u001b[33m\"\u001b[39m, exceptions)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\socket.py:849\u001b[39m, in \u001b[36mcreate_connection\u001b[39m\u001b[34m(address, timeout, source_address, all_errors)\u001b[39m\n\u001b[32m 848\u001b[39m sock.bind(source_address)\n\u001b[32m--> \u001b[39m\u001b[32m849\u001b[39m \u001b[43msock\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43msa\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 850\u001b[39m \u001b[38;5;66;03m# Break explicitly a reference cycle\u001b[39;00m\n", + "\u001b[31mConnectionRefusedError\u001b[39m: [WinError 10061] No connection could be made because the target machine actively refused it", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:143\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 142\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = \u001b[43mengine\u001b[49m\u001b[43m.\u001b[49m\u001b[43mraw_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3301\u001b[39m, in \u001b[36mEngine.raw_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3280\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Return a \"raw\" DBAPI connection from the connection pool.\u001b[39;00m\n\u001b[32m 3281\u001b[39m \n\u001b[32m 3282\u001b[39m \u001b[33;03mThe returned object is a proxied version of the DBAPI\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3299\u001b[39m \n\u001b[32m 3300\u001b[39m \u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3301\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:447\u001b[39m, in \u001b[36mPool.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 440\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Return a DBAPI connection from the pool.\u001b[39;00m\n\u001b[32m 441\u001b[39m \n\u001b[32m 442\u001b[39m \u001b[33;03mThe connection is instrumented such that when its\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 445\u001b[39m \n\u001b[32m 446\u001b[39m \u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m447\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionFairy\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_checkout\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:1264\u001b[39m, in \u001b[36m_ConnectionFairy._checkout\u001b[39m\u001b[34m(cls, pool, threadconns, fairy)\u001b[39m\n\u001b[32m 1263\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m fairy:\n\u001b[32m-> \u001b[39m\u001b[32m1264\u001b[39m fairy = \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcheckout\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1266\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m threadconns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:711\u001b[39m, in \u001b[36m_ConnectionRecord.checkout\u001b[39m\u001b[34m(cls, pool)\u001b[39m\n\u001b[32m 710\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m711\u001b[39m rec = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_do_get\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 713\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:177\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m177\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 178\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_dec_overflow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:175\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 174\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_create_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:388\u001b[39m, in \u001b[36mPool._create_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 386\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Called by subclasses to create a new ConnectionRecord.\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m388\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:673\u001b[39m, in \u001b[36m_ConnectionRecord.__init__\u001b[39m\u001b[34m(self, pool, connect)\u001b[39m\n\u001b[32m 672\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connect:\n\u001b[32m--> \u001b[39m\u001b[32m673\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__connect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 674\u001b[39m \u001b[38;5;28mself\u001b[39m.finalize_callback = deque()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:899\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 898\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[32m--> \u001b[39m\u001b[32m899\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 900\u001b[39m \u001b[43m \u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mlogger\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdebug\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mError on connect(): \u001b[39;49m\u001b[38;5;132;43;01m%s\u001b[39;49;00m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43me\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:895\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 894\u001b[39m \u001b[38;5;28mself\u001b[39m.starttime = time.time()\n\u001b[32m--> \u001b[39m\u001b[32m895\u001b[39m \u001b[38;5;28mself\u001b[39m.dbapi_connection = connection = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_invoke_creator\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 896\u001b[39m pool.logger.debug(\u001b[33m\"\u001b[39m\u001b[33mCreated new connection \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[33m\"\u001b[39m, connection)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\create.py:661\u001b[39m, in \u001b[36mcreate_engine..connect\u001b[39m\u001b[34m(connection_record)\u001b[39m\n\u001b[32m 659\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m connection\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mdialect\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\default.py:629\u001b[39m, in \u001b[36mDefaultDialect.connect\u001b[39m\u001b[34m(self, *cargs, **cparams)\u001b[39m\n\u001b[32m 627\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m, *cargs: Any, **cparams: Any) -> DBAPIConnection:\n\u001b[32m 628\u001b[39m \u001b[38;5;66;03m# inherits the docstring from interfaces.Dialect.connect\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m629\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mloaded_dbapi\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:365\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, user, password, host, database, unix_socket, port, charset, collation, sql_mode, read_default_file, conv, use_unicode, client_flag, cursorclass, init_command, connect_timeout, read_default_group, autocommit, local_infile, max_allowed_packet, defer_connect, auth_plugin_map, read_timeout, write_timeout, bind_address, binary_prefix, program_name, server_public_key, ssl, ssl_ca, ssl_cert, ssl_disabled, ssl_key, ssl_key_password, ssl_verify_cert, ssl_verify_identity, compress, named_pipe, passwd, db)\u001b[39m\n\u001b[32m 364\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m365\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:723\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 722\u001b[39m \u001b[38;5;28mprint\u001b[39m(exc.traceback)\n\u001b[32m--> \u001b[39m\u001b[32m723\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[32m 725\u001b[39m \u001b[38;5;66;03m# If e is neither DatabaseError or IOError, It's a bug.\u001b[39;00m\n\u001b[32m 726\u001b[39m \u001b[38;5;66;03m# But raising AssertionError hides original error.\u001b[39;00m\n\u001b[32m 727\u001b[39m \u001b[38;5;66;03m# So just reraise it.\u001b[39;00m\n", + "\u001b[31mOperationalError\u001b[39m: (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 31\u001b[39m\n\u001b[32m 29\u001b[39m \u001b[38;5;66;03m# Quick test: verify connection\u001b[39;00m\n\u001b[32m 30\u001b[39m test_query = \u001b[33m\"\u001b[39m\u001b[33mSELECT * FROM rental LIMIT 5;\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m---> \u001b[39m\u001b[32m31\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_sql\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtest_query\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[32m 34\u001b[39m \u001b[38;5;66;03m# ============================================================\u001b[39;00m\n\u001b[32m 35\u001b[39m \u001b[38;5;66;03m# 2. Function: rentals_month\u001b[39;00m\n\u001b[32m 36\u001b[39m \u001b[38;5;66;03m# ============================================================\u001b[39;00m\n\u001b[32m 38\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mrentals_month\u001b[39m(engine, month, year):\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:706\u001b[39m, in \u001b[36mread_sql\u001b[39m\u001b[34m(sql, con, index_col, coerce_float, params, parse_dates, columns, chunksize, dtype_backend, dtype)\u001b[39m\n\u001b[32m 703\u001b[39m dtype_backend = \u001b[33m\"\u001b[39m\u001b[33mnumpy\u001b[39m\u001b[33m\"\u001b[39m \u001b[38;5;66;03m# type: ignore[assignment]\u001b[39;00m\n\u001b[32m 704\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m dtype_backend \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m lib.no_default\n\u001b[32m--> \u001b[39m\u001b[32m706\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mpandasSQL_builder\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcon\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m pandas_sql:\n\u001b[32m 707\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(pandas_sql, SQLiteDatabase):\n\u001b[32m 708\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m pandas_sql.read_query(\n\u001b[32m 709\u001b[39m sql,\n\u001b[32m 710\u001b[39m index_col=index_col,\n\u001b[32m (...)\u001b[39m\u001b[32m 716\u001b[39m dtype=dtype,\n\u001b[32m 717\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:908\u001b[39m, in \u001b[36mpandasSQL_builder\u001b[39m\u001b[34m(con, schema, need_transaction)\u001b[39m\n\u001b[32m 905\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mImportError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mUsing URI string without sqlalchemy installed.\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 907\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m sqlalchemy \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, (\u001b[38;5;28mstr\u001b[39m, sqlalchemy.engine.Connectable)):\n\u001b[32m--> \u001b[39m\u001b[32m908\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mSQLDatabase\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcon\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mschema\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mneed_transaction\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 910\u001b[39m adbc = import_optional_dependency(\u001b[33m\"\u001b[39m\u001b[33madbc_driver_manager.dbapi\u001b[39m\u001b[33m\"\u001b[39m, errors=\u001b[33m\"\u001b[39m\u001b[33mignore\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 911\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m adbc \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, adbc.Connection):\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:1648\u001b[39m, in \u001b[36mSQLDatabase.__init__\u001b[39m\u001b[34m(self, con, schema, need_transaction)\u001b[39m\n\u001b[32m 1646\u001b[39m \u001b[38;5;28mself\u001b[39m.exit_stack.callback(con.dispose)\n\u001b[32m 1647\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, Engine):\n\u001b[32m-> \u001b[39m\u001b[32m1648\u001b[39m con = \u001b[38;5;28mself\u001b[39m.exit_stack.enter_context(\u001b[43mcon\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[32m 1649\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m need_transaction \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m con.in_transaction():\n\u001b[32m 1650\u001b[39m \u001b[38;5;28mself\u001b[39m.exit_stack.enter_context(con.begin())\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3277\u001b[39m, in \u001b[36mEngine.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3254\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> Connection:\n\u001b[32m 3255\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a new :class:`_engine.Connection` object.\u001b[39;00m\n\u001b[32m 3256\u001b[39m \n\u001b[32m 3257\u001b[39m \u001b[33;03m The :class:`_engine.Connection` acts as a Python context manager, so\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3274\u001b[39m \n\u001b[32m 3275\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3277\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_connection_cls\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:145\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = engine.raw_connection()\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[32m--> \u001b[39m\u001b[32m145\u001b[39m \u001b[43mConnection\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_handle_dbapi_exception_noconnection\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 146\u001b[39m \u001b[43m \u001b[49m\u001b[43merr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdialect\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\n\u001b[32m 147\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 148\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n\u001b[32m 149\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:2440\u001b[39m, in \u001b[36mConnection._handle_dbapi_exception_noconnection\u001b[39m\u001b[34m(cls, e, dialect, engine, is_disconnect, invalidate_pool_on_disconnect, is_pre_ping)\u001b[39m\n\u001b[32m 2438\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m should_wrap:\n\u001b[32m 2439\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m sqlalchemy_exception \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m2440\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m sqlalchemy_exception.with_traceback(exc_info[\u001b[32m2\u001b[39m]) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01me\u001b[39;00m\n\u001b[32m 2441\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 2442\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_info[\u001b[32m1\u001b[39m] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:143\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 141\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connection \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 142\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = \u001b[43mengine\u001b[49m\u001b[43m.\u001b[49m\u001b[43mraw_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[32m 145\u001b[39m Connection._handle_dbapi_exception_noconnection(\n\u001b[32m 146\u001b[39m err, dialect, engine\n\u001b[32m 147\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3301\u001b[39m, in \u001b[36mEngine.raw_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3279\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mraw_connection\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> PoolProxiedConnection:\n\u001b[32m 3280\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a \"raw\" DBAPI connection from the connection pool.\u001b[39;00m\n\u001b[32m 3281\u001b[39m \n\u001b[32m 3282\u001b[39m \u001b[33;03m The returned object is a proxied version of the DBAPI\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3299\u001b[39m \n\u001b[32m 3300\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3301\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:447\u001b[39m, in \u001b[36mPool.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 439\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> PoolProxiedConnection:\n\u001b[32m 440\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a DBAPI connection from the pool.\u001b[39;00m\n\u001b[32m 441\u001b[39m \n\u001b[32m 442\u001b[39m \u001b[33;03m The connection is instrumented such that when its\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 445\u001b[39m \n\u001b[32m 446\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m447\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionFairy\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_checkout\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:1264\u001b[39m, in \u001b[36m_ConnectionFairy._checkout\u001b[39m\u001b[34m(cls, pool, threadconns, fairy)\u001b[39m\n\u001b[32m 1256\u001b[39m \u001b[38;5;129m@classmethod\u001b[39m\n\u001b[32m 1257\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m_checkout\u001b[39m(\n\u001b[32m 1258\u001b[39m \u001b[38;5;28mcls\u001b[39m,\n\u001b[32m (...)\u001b[39m\u001b[32m 1261\u001b[39m fairy: Optional[_ConnectionFairy] = \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[32m 1262\u001b[39m ) -> _ConnectionFairy:\n\u001b[32m 1263\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m fairy:\n\u001b[32m-> \u001b[39m\u001b[32m1264\u001b[39m fairy = \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcheckout\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1266\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m threadconns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 1267\u001b[39m threadconns.current = weakref.ref(fairy)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:711\u001b[39m, in \u001b[36m_ConnectionRecord.checkout\u001b[39m\u001b[34m(cls, pool)\u001b[39m\n\u001b[32m 709\u001b[39m rec = cast(_ConnectionRecord, pool._do_get())\n\u001b[32m 710\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m711\u001b[39m rec = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_do_get\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 713\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m 714\u001b[39m dbapi_connection = rec.get_connection()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:177\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._create_connection()\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m177\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 178\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_dec_overflow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 179\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 222\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_value \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 226\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:175\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 173\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m._inc_overflow():\n\u001b[32m 174\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_create_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m 177\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m util.safe_reraise():\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:388\u001b[39m, in \u001b[36mPool._create_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 385\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m_create_connection\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> ConnectionPoolEntry:\n\u001b[32m 386\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Called by subclasses to create a new ConnectionRecord.\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m388\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:673\u001b[39m, in \u001b[36m_ConnectionRecord.__init__\u001b[39m\u001b[34m(self, pool, connect)\u001b[39m\n\u001b[32m 671\u001b[39m \u001b[38;5;28mself\u001b[39m.__pool = pool\n\u001b[32m 672\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connect:\n\u001b[32m--> \u001b[39m\u001b[32m673\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__connect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 674\u001b[39m \u001b[38;5;28mself\u001b[39m.finalize_callback = deque()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:899\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 897\u001b[39m \u001b[38;5;28mself\u001b[39m.fresh = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m 898\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[32m--> \u001b[39m\u001b[32m899\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 900\u001b[39m \u001b[43m \u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mlogger\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdebug\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mError on connect(): \u001b[39;49m\u001b[38;5;132;43;01m%s\u001b[39;49;00m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43me\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 901\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 902\u001b[39m \u001b[38;5;66;03m# in SQLAlchemy 1.4 the first_connect event is not used by\u001b[39;00m\n\u001b[32m 903\u001b[39m \u001b[38;5;66;03m# the engine, so this will usually not be set\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 222\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_value \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 226\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:895\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 893\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m 894\u001b[39m \u001b[38;5;28mself\u001b[39m.starttime = time.time()\n\u001b[32m--> \u001b[39m\u001b[32m895\u001b[39m \u001b[38;5;28mself\u001b[39m.dbapi_connection = connection = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_invoke_creator\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 896\u001b[39m pool.logger.debug(\u001b[33m\"\u001b[39m\u001b[33mCreated new connection \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[33m\"\u001b[39m, connection)\n\u001b[32m 897\u001b[39m \u001b[38;5;28mself\u001b[39m.fresh = \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\create.py:661\u001b[39m, in \u001b[36mcreate_engine..connect\u001b[39m\u001b[34m(connection_record)\u001b[39m\n\u001b[32m 658\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connection \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 659\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m connection\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mdialect\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\default.py:629\u001b[39m, in \u001b[36mDefaultDialect.connect\u001b[39m\u001b[34m(self, *cargs, **cparams)\u001b[39m\n\u001b[32m 627\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m, *cargs: Any, **cparams: Any) -> DBAPIConnection:\n\u001b[32m 628\u001b[39m \u001b[38;5;66;03m# inherits the docstring from interfaces.Dialect.connect\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m629\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mloaded_dbapi\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:365\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, user, password, host, database, unix_socket, port, charset, collation, sql_mode, read_default_file, conv, use_unicode, client_flag, cursorclass, init_command, connect_timeout, read_default_group, autocommit, local_infile, max_allowed_packet, defer_connect, auth_plugin_map, read_timeout, write_timeout, bind_address, binary_prefix, program_name, server_public_key, ssl, ssl_ca, ssl_cert, ssl_disabled, ssl_key, ssl_key_password, ssl_verify_cert, ssl_verify_identity, compress, named_pipe, passwd, db)\u001b[39m\n\u001b[32m 363\u001b[39m \u001b[38;5;28mself\u001b[39m._sock = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 364\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m365\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:723\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 721\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m DEBUG:\n\u001b[32m 722\u001b[39m \u001b[38;5;28mprint\u001b[39m(exc.traceback)\n\u001b[32m--> \u001b[39m\u001b[32m723\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[32m 725\u001b[39m \u001b[38;5;66;03m# If e is neither DatabaseError or IOError, It's a bug.\u001b[39;00m\n\u001b[32m 726\u001b[39m \u001b[38;5;66;03m# But raising AssertionError hides original error.\u001b[39;00m\n\u001b[32m 727\u001b[39m \u001b[38;5;66;03m# So just reraise it.\u001b[39;00m\n\u001b[32m 728\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n", + "\u001b[31mOperationalError\u001b[39m: (pymysql.err.OperationalError) (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")\n(Background on this error at: https://sqlalche.me/e/20/e3q8)" + ] + } + ], + "source": [ + "#!/usr/bin/env python\n", + "# -*- coding: utf-8 -*-\n", + "\"\"\"\n", + "LAB | Connecting Python to SQL\n", + "Sakila Database - Rental Activity Comparison (May vs June 2005)\n", + "Author: Abhishek Rahul\n", + "\"\"\"\n", + "\n", + "# ============================================================\n", + "# 1. Import Libraries & Establish Connection\n", + "# ============================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "from sqlalchemy import create_engine\n", + "\n", + "# Database connection settings — UPDATE YOUR PASSWORD HERE\n", + "db_user = \"root\"\n", + "db_password = \"Ironhck2025\" # <-- Replace with your MySQL password\n", + "db_host = \"localhost\"\n", + "db_name = \"sakila\"\n", + "\n", + "# Create the connection string and engine\n", + "connection_string = f\"mysql+pymysql://{db_user}:{db_password}@{db_host}/{db_name}\"\n", + "engine = create_engine(connection_string)\n", + "\n", + "print(\"Connection established successfully!\")\n", + "\n", + "# Quick test: verify connection\n", + "test_query = \"SELECT * FROM rental LIMIT 5;\"\n", + "print(pd.read_sql(test_query, engine))\n", + "\n", + "\n", + "# ============================================================\n", + "# 2. Function: rentals_month\n", + "# ============================================================\n", + "\n", + "def rentals_month(engine, month, year):\n", + " \"\"\"\n", + " Retrieves rental data for a specific month and year from the Sakila database.\n", + "\n", + " Parameters:\n", + " -----------\n", + " engine : sqlalchemy.engine.Engine\n", + " Database connection engine for the Sakila database.\n", + " month : int\n", + " Month for which to retrieve rental data (1-12).\n", + " year : int\n", + " Year for which to retrieve rental data.\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " DataFrame containing rental records for the specified month and year.\n", + " \"\"\"\n", + " query = f\"\"\"\n", + " SELECT *\n", + " FROM rental\n", + " WHERE MONTH(rental_date) = {month}\n", + " AND YEAR(rental_date) = {year};\n", + " \"\"\"\n", + "\n", + " rental_data = pd.read_sql(query, engine)\n", + "\n", + " return rental_data\n", + "\n", + "\n", + "# Test: Retrieve rentals for May and June 2005\n", + "may_rentals = rentals_month(engine, 5, 2005)\n", + "print(f\"\\nMay 2005 rentals: {len(may_rentals)} records\")\n", + "print(may_rentals.head())\n", + "\n", + "june_rentals = rentals_month(engine, 6, 2005)\n", + "print(f\"\\nJune 2005 rentals: {len(june_rentals)} records\")\n", + "print(june_rentals.head())\n", + "\n", + "\n", + "# ============================================================\n", + "# 3. Function: rental_count_month\n", + "# ============================================================\n", + "\n", + "def rental_count_month(df, month, year):\n", + " \"\"\"\n", + " Counts the number of rentals per customer for a given month and year.\n", + "\n", + " Parameters:\n", + " -----------\n", + " df : pd.DataFrame\n", + " DataFrame containing rental data (output of rentals_month).\n", + " month : int\n", + " Month used for naming the rental count column.\n", + " year : int\n", + " Year used for naming the rental count column.\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " DataFrame with customer_id and a column named 'rentals_MM_YYYY'\n", + " containing the count of rentals per customer.\n", + " \"\"\"\n", + " # Create the dynamic column name (e.g., 'rentals_05_2005')\n", + " column_name = f\"rentals_{month:02d}_{year}\"\n", + "\n", + " # Group by customer_id and count rentals\n", + " rental_counts = (\n", + " df.groupby(\"customer_id\")\n", + " .agg(rental_count=(\"rental_id\", \"count\"))\n", + " .reset_index()\n", + " .rename(columns={\"rental_count\": column_name})\n", + " )\n", + "\n", + " return rental_counts\n", + "\n", + "\n", + "# Get rental counts for both months\n", + "may_counts = rental_count_month(may_rentals, 5, 2005)\n", + "print(f\"\\nUnique customers in May 2005: {len(may_counts)}\")\n", + "print(may_counts.head(10))\n", + "\n", + "june_counts = rental_count_month(june_rentals, 6, 2005)\n", + "print(f\"\\nUnique customers in June 2005: {len(june_counts)}\")\n", + "print(june_counts.head(10))\n", + "\n", + "\n", + "# ============================================================\n", + "# 4. Function: compare_rentals\n", + "# ============================================================\n", + "\n", + "def compare_rentals(df1, df2):\n", + " \"\"\"\n", + " Compares rental activity between two months by merging the DataFrames\n", + " and calculating the difference in rental counts.\n", + "\n", + " Parameters:\n", + " -----------\n", + " df1 : pd.DataFrame\n", + " First month's rental count DataFrame (output of rental_count_month).\n", + " df2 : pd.DataFrame\n", + " Second month's rental count DataFrame (output of rental_count_month).\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " Combined DataFrame with customer_id, both months' rental counts,\n", + " and a 'difference' column (df2 values - df1 values).\n", + " \"\"\"\n", + " # Merge on customer_id using outer join to include all customers\n", + " combined = df1.merge(df2, on=\"customer_id\", how=\"outer\")\n", + "\n", + " # Fill NaN with 0 (customers active in one month but not the other)\n", + " combined = combined.fillna(0)\n", + "\n", + " # Get the rental count column names (the non-customer_id columns)\n", + " rental_columns = [col for col in combined.columns if col != \"customer_id\"]\n", + "\n", + " # Calculate the difference (second month - first month)\n", + " combined[\"difference\"] = combined[rental_columns[1]] - combined[rental_columns[0]]\n", + "\n", + " return combined\n", + "\n", + "\n", + "# Compare May vs June 2005\n", + "comparison = compare_rentals(may_counts, june_counts)\n", + "print(f\"\\nTotal customers across both months: {len(comparison)}\")\n", + "print(comparison.head(10))\n", + "\n", + "\n", + "# ============================================================\n", + "# 5. Analysis & Insights\n", + "# ============================================================\n", + "\n", + "print(\"\\n\" + \"=\" * 55)\n", + "print(\" RENTAL COMPARISON: MAY vs JUNE 2005\")\n", + "print(\"=\" * 55)\n", + "print(f\" Total customers in May 2005: {len(may_counts)}\")\n", + "print(f\" Total customers in June 2005: {len(june_counts)}\")\n", + "print(f\" Customers active in both: {len(comparison[(comparison['rentals_05_2005'] > 0) & (comparison['rentals_06_2005'] > 0)])}\")\n", + "print(f\" Only active in May: {len(comparison[(comparison['rentals_05_2005'] > 0) & (comparison['rentals_06_2005'] == 0)])}\")\n", + "print(f\" Only active in June: {len(comparison[(comparison['rentals_05_2005'] == 0) & (comparison['rentals_06_2005'] > 0)])}\")\n", + "print(\"-\" * 55)\n", + "print(f\" Avg rentals per customer (May): {comparison['rentals_05_2005'].mean():.2f}\")\n", + "print(f\" Avg rentals per customer (June): {comparison['rentals_06_2005'].mean():.2f}\")\n", + "print(f\" Avg difference (June - May): {comparison['difference'].mean():.2f}\")\n", + "print(\"=\" * 55)\n", + "\n", + "# Customers who rented more in June vs May\n", + "more_in_june = comparison[comparison[\"difference\"] > 0]\n", + "more_in_may = comparison[comparison[\"difference\"] < 0]\n", + "same = comparison[comparison[\"difference\"] == 0]\n", + "\n", + "print(f\"\\nCustomers who rented MORE in June: {len(more_in_june)}\")\n", + "print(f\"Customers who rented MORE in May: {len(more_in_may)}\")\n", + "print(f\"Customers with SAME activity: {len(same)}\")\n", + "\n", + "# Top 10 increases and decreases\n", + "print(\"\\nTop 10 customers with biggest increase (May -> June):\")\n", + "print(comparison.nlargest(10, \"difference\"))\n", + "\n", + "print(\"\\nTop 10 customers with biggest decrease (May -> June):\")\n", + "print(comparison.nsmallest(10, \"difference\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5b50765-1b2c-4e34-9e6c-e7ce04eccd74", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python sql.ipynb b/python sql.ipynb new file mode 100644 index 0000000..4af63ac --- /dev/null +++ b/python sql.ipynb @@ -0,0 +1,310 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "abeedd4a-10ee-49fd-9edf-9825974e963b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connection established successfully!\n" + ] + }, + { + "ename": "OperationalError", + "evalue": "(pymysql.err.OperationalError) (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")\n(Background on this error at: https://sqlalche.me/e/20/e3q8)", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mConnectionRefusedError\u001b[39m Traceback (most recent call last)", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:661\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 660\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m sock = \u001b[43msocket\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcreate_connection\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 662\u001b[39m \u001b[43m \u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mhost\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mport\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect_timeout\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\n\u001b[32m 663\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 664\u001b[39m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\socket.py:864\u001b[39m, in \u001b[36mcreate_connection\u001b[39m\u001b[34m(address, timeout, source_address, all_errors)\u001b[39m\n\u001b[32m 863\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m all_errors:\n\u001b[32m--> \u001b[39m\u001b[32m864\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exceptions[\u001b[32m0\u001b[39m]\n\u001b[32m 865\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m ExceptionGroup(\u001b[33m\"\u001b[39m\u001b[33mcreate_connection failed\u001b[39m\u001b[33m\"\u001b[39m, exceptions)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\socket.py:849\u001b[39m, in \u001b[36mcreate_connection\u001b[39m\u001b[34m(address, timeout, source_address, all_errors)\u001b[39m\n\u001b[32m 848\u001b[39m sock.bind(source_address)\n\u001b[32m--> \u001b[39m\u001b[32m849\u001b[39m \u001b[43msock\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43msa\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 850\u001b[39m \u001b[38;5;66;03m# Break explicitly a reference cycle\u001b[39;00m\n", + "\u001b[31mConnectionRefusedError\u001b[39m: [WinError 10061] No connection could be made because the target machine actively refused it", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:143\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 142\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = \u001b[43mengine\u001b[49m\u001b[43m.\u001b[49m\u001b[43mraw_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3301\u001b[39m, in \u001b[36mEngine.raw_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3280\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Return a \"raw\" DBAPI connection from the connection pool.\u001b[39;00m\n\u001b[32m 3281\u001b[39m \n\u001b[32m 3282\u001b[39m \u001b[33;03mThe returned object is a proxied version of the DBAPI\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3299\u001b[39m \n\u001b[32m 3300\u001b[39m \u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3301\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:447\u001b[39m, in \u001b[36mPool.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 440\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Return a DBAPI connection from the pool.\u001b[39;00m\n\u001b[32m 441\u001b[39m \n\u001b[32m 442\u001b[39m \u001b[33;03mThe connection is instrumented such that when its\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 445\u001b[39m \n\u001b[32m 446\u001b[39m \u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m447\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionFairy\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_checkout\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:1264\u001b[39m, in \u001b[36m_ConnectionFairy._checkout\u001b[39m\u001b[34m(cls, pool, threadconns, fairy)\u001b[39m\n\u001b[32m 1263\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m fairy:\n\u001b[32m-> \u001b[39m\u001b[32m1264\u001b[39m fairy = \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcheckout\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1266\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m threadconns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:711\u001b[39m, in \u001b[36m_ConnectionRecord.checkout\u001b[39m\u001b[34m(cls, pool)\u001b[39m\n\u001b[32m 710\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m711\u001b[39m rec = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_do_get\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 713\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:177\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m177\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 178\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_dec_overflow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:175\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 174\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_create_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:388\u001b[39m, in \u001b[36mPool._create_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 386\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Called by subclasses to create a new ConnectionRecord.\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m388\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:673\u001b[39m, in \u001b[36m_ConnectionRecord.__init__\u001b[39m\u001b[34m(self, pool, connect)\u001b[39m\n\u001b[32m 672\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connect:\n\u001b[32m--> \u001b[39m\u001b[32m673\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__connect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 674\u001b[39m \u001b[38;5;28mself\u001b[39m.finalize_callback = deque()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:899\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 898\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[32m--> \u001b[39m\u001b[32m899\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 900\u001b[39m \u001b[43m \u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mlogger\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdebug\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mError on connect(): \u001b[39;49m\u001b[38;5;132;43;01m%s\u001b[39;49;00m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43me\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:895\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 894\u001b[39m \u001b[38;5;28mself\u001b[39m.starttime = time.time()\n\u001b[32m--> \u001b[39m\u001b[32m895\u001b[39m \u001b[38;5;28mself\u001b[39m.dbapi_connection = connection = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_invoke_creator\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 896\u001b[39m pool.logger.debug(\u001b[33m\"\u001b[39m\u001b[33mCreated new connection \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[33m\"\u001b[39m, connection)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\create.py:661\u001b[39m, in \u001b[36mcreate_engine..connect\u001b[39m\u001b[34m(connection_record)\u001b[39m\n\u001b[32m 659\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m connection\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mdialect\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\default.py:629\u001b[39m, in \u001b[36mDefaultDialect.connect\u001b[39m\u001b[34m(self, *cargs, **cparams)\u001b[39m\n\u001b[32m 627\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m, *cargs: Any, **cparams: Any) -> DBAPIConnection:\n\u001b[32m 628\u001b[39m \u001b[38;5;66;03m# inherits the docstring from interfaces.Dialect.connect\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m629\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mloaded_dbapi\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:365\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, user, password, host, database, unix_socket, port, charset, collation, sql_mode, read_default_file, conv, use_unicode, client_flag, cursorclass, init_command, connect_timeout, read_default_group, autocommit, local_infile, max_allowed_packet, defer_connect, auth_plugin_map, read_timeout, write_timeout, bind_address, binary_prefix, program_name, server_public_key, ssl, ssl_ca, ssl_cert, ssl_disabled, ssl_key, ssl_key_password, ssl_verify_cert, ssl_verify_identity, compress, named_pipe, passwd, db)\u001b[39m\n\u001b[32m 364\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m365\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:723\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 722\u001b[39m \u001b[38;5;28mprint\u001b[39m(exc.traceback)\n\u001b[32m--> \u001b[39m\u001b[32m723\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[32m 725\u001b[39m \u001b[38;5;66;03m# If e is neither DatabaseError or IOError, It's a bug.\u001b[39;00m\n\u001b[32m 726\u001b[39m \u001b[38;5;66;03m# But raising AssertionError hides original error.\u001b[39;00m\n\u001b[32m 727\u001b[39m \u001b[38;5;66;03m# So just reraise it.\u001b[39;00m\n", + "\u001b[31mOperationalError\u001b[39m: (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 31\u001b[39m\n\u001b[32m 29\u001b[39m \u001b[38;5;66;03m# Quick test: verify connection\u001b[39;00m\n\u001b[32m 30\u001b[39m test_query = \u001b[33m\"\u001b[39m\u001b[33mSELECT * FROM rental LIMIT 5;\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m---> \u001b[39m\u001b[32m31\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_sql\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtest_query\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[32m 34\u001b[39m \u001b[38;5;66;03m# ============================================================\u001b[39;00m\n\u001b[32m 35\u001b[39m \u001b[38;5;66;03m# 2. Function: rentals_month\u001b[39;00m\n\u001b[32m 36\u001b[39m \u001b[38;5;66;03m# ============================================================\u001b[39;00m\n\u001b[32m 38\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mrentals_month\u001b[39m(engine, month, year):\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:706\u001b[39m, in \u001b[36mread_sql\u001b[39m\u001b[34m(sql, con, index_col, coerce_float, params, parse_dates, columns, chunksize, dtype_backend, dtype)\u001b[39m\n\u001b[32m 703\u001b[39m dtype_backend = \u001b[33m\"\u001b[39m\u001b[33mnumpy\u001b[39m\u001b[33m\"\u001b[39m \u001b[38;5;66;03m# type: ignore[assignment]\u001b[39;00m\n\u001b[32m 704\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m dtype_backend \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m lib.no_default\n\u001b[32m--> \u001b[39m\u001b[32m706\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mpandasSQL_builder\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcon\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m pandas_sql:\n\u001b[32m 707\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(pandas_sql, SQLiteDatabase):\n\u001b[32m 708\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m pandas_sql.read_query(\n\u001b[32m 709\u001b[39m sql,\n\u001b[32m 710\u001b[39m index_col=index_col,\n\u001b[32m (...)\u001b[39m\u001b[32m 716\u001b[39m dtype=dtype,\n\u001b[32m 717\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:908\u001b[39m, in \u001b[36mpandasSQL_builder\u001b[39m\u001b[34m(con, schema, need_transaction)\u001b[39m\n\u001b[32m 905\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mImportError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mUsing URI string without sqlalchemy installed.\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 907\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m sqlalchemy \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, (\u001b[38;5;28mstr\u001b[39m, sqlalchemy.engine.Connectable)):\n\u001b[32m--> \u001b[39m\u001b[32m908\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mSQLDatabase\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcon\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mschema\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mneed_transaction\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 910\u001b[39m adbc = import_optional_dependency(\u001b[33m\"\u001b[39m\u001b[33madbc_driver_manager.dbapi\u001b[39m\u001b[33m\"\u001b[39m, errors=\u001b[33m\"\u001b[39m\u001b[33mignore\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 911\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m adbc \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, adbc.Connection):\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pandas\\io\\sql.py:1648\u001b[39m, in \u001b[36mSQLDatabase.__init__\u001b[39m\u001b[34m(self, con, schema, need_transaction)\u001b[39m\n\u001b[32m 1646\u001b[39m \u001b[38;5;28mself\u001b[39m.exit_stack.callback(con.dispose)\n\u001b[32m 1647\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(con, Engine):\n\u001b[32m-> \u001b[39m\u001b[32m1648\u001b[39m con = \u001b[38;5;28mself\u001b[39m.exit_stack.enter_context(\u001b[43mcon\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[32m 1649\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m need_transaction \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m con.in_transaction():\n\u001b[32m 1650\u001b[39m \u001b[38;5;28mself\u001b[39m.exit_stack.enter_context(con.begin())\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3277\u001b[39m, in \u001b[36mEngine.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3254\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> Connection:\n\u001b[32m 3255\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a new :class:`_engine.Connection` object.\u001b[39;00m\n\u001b[32m 3256\u001b[39m \n\u001b[32m 3257\u001b[39m \u001b[33;03m The :class:`_engine.Connection` acts as a Python context manager, so\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3274\u001b[39m \n\u001b[32m 3275\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3277\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_connection_cls\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:145\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = engine.raw_connection()\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[32m--> \u001b[39m\u001b[32m145\u001b[39m \u001b[43mConnection\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_handle_dbapi_exception_noconnection\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m 146\u001b[39m \u001b[43m \u001b[49m\u001b[43merr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdialect\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\n\u001b[32m 147\u001b[39m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 148\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n\u001b[32m 149\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:2440\u001b[39m, in \u001b[36mConnection._handle_dbapi_exception_noconnection\u001b[39m\u001b[34m(cls, e, dialect, engine, is_disconnect, invalidate_pool_on_disconnect, is_pre_ping)\u001b[39m\n\u001b[32m 2438\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m should_wrap:\n\u001b[32m 2439\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m sqlalchemy_exception \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m2440\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m sqlalchemy_exception.with_traceback(exc_info[\u001b[32m2\u001b[39m]) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01me\u001b[39;00m\n\u001b[32m 2441\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 2442\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_info[\u001b[32m1\u001b[39m] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:143\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, engine, connection, _has_events, _allow_revalidate, _allow_autobegin)\u001b[39m\n\u001b[32m 141\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connection \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 142\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m143\u001b[39m \u001b[38;5;28mself\u001b[39m._dbapi_connection = \u001b[43mengine\u001b[49m\u001b[43m.\u001b[49m\u001b[43mraw_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 144\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m dialect.loaded_dbapi.Error \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[32m 145\u001b[39m Connection._handle_dbapi_exception_noconnection(\n\u001b[32m 146\u001b[39m err, dialect, engine\n\u001b[32m 147\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\base.py:3301\u001b[39m, in \u001b[36mEngine.raw_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 3279\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mraw_connection\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> PoolProxiedConnection:\n\u001b[32m 3280\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a \"raw\" DBAPI connection from the connection pool.\u001b[39;00m\n\u001b[32m 3281\u001b[39m \n\u001b[32m 3282\u001b[39m \u001b[33;03m The returned object is a proxied version of the DBAPI\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 3299\u001b[39m \n\u001b[32m 3300\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m3301\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:447\u001b[39m, in \u001b[36mPool.connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 439\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> PoolProxiedConnection:\n\u001b[32m 440\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return a DBAPI connection from the pool.\u001b[39;00m\n\u001b[32m 441\u001b[39m \n\u001b[32m 442\u001b[39m \u001b[33;03m The connection is instrumented such that when its\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 445\u001b[39m \n\u001b[32m 446\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m447\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionFairy\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_checkout\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:1264\u001b[39m, in \u001b[36m_ConnectionFairy._checkout\u001b[39m\u001b[34m(cls, pool, threadconns, fairy)\u001b[39m\n\u001b[32m 1256\u001b[39m \u001b[38;5;129m@classmethod\u001b[39m\n\u001b[32m 1257\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m_checkout\u001b[39m(\n\u001b[32m 1258\u001b[39m \u001b[38;5;28mcls\u001b[39m,\n\u001b[32m (...)\u001b[39m\u001b[32m 1261\u001b[39m fairy: Optional[_ConnectionFairy] = \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[32m 1262\u001b[39m ) -> _ConnectionFairy:\n\u001b[32m 1263\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m fairy:\n\u001b[32m-> \u001b[39m\u001b[32m1264\u001b[39m fairy = \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcheckout\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpool\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 1266\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m threadconns \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 1267\u001b[39m threadconns.current = weakref.ref(fairy)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:711\u001b[39m, in \u001b[36m_ConnectionRecord.checkout\u001b[39m\u001b[34m(cls, pool)\u001b[39m\n\u001b[32m 709\u001b[39m rec = cast(_ConnectionRecord, pool._do_get())\n\u001b[32m 710\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m711\u001b[39m rec = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_do_get\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 713\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m 714\u001b[39m dbapi_connection = rec.get_connection()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:177\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m._create_connection()\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m177\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 178\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_dec_overflow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 179\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 222\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_value \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 226\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\impl.py:175\u001b[39m, in \u001b[36mQueuePool._do_get\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 173\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m._inc_overflow():\n\u001b[32m 174\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m175\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_create_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m:\n\u001b[32m 177\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m util.safe_reraise():\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:388\u001b[39m, in \u001b[36mPool._create_connection\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 385\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m_create_connection\u001b[39m(\u001b[38;5;28mself\u001b[39m) -> ConnectionPoolEntry:\n\u001b[32m 386\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Called by subclasses to create a new ConnectionRecord.\"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m388\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ConnectionRecord\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:673\u001b[39m, in \u001b[36m_ConnectionRecord.__init__\u001b[39m\u001b[34m(self, pool, connect)\u001b[39m\n\u001b[32m 671\u001b[39m \u001b[38;5;28mself\u001b[39m.__pool = pool\n\u001b[32m 672\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connect:\n\u001b[32m--> \u001b[39m\u001b[32m673\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__connect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 674\u001b[39m \u001b[38;5;28mself\u001b[39m.finalize_callback = deque()\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:899\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 897\u001b[39m \u001b[38;5;28mself\u001b[39m.fresh = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m 898\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[32m--> \u001b[39m\u001b[32m899\u001b[39m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mwith\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mutil\u001b[49m\u001b[43m.\u001b[49m\u001b[43msafe_reraise\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[32m 900\u001b[39m \u001b[43m \u001b[49m\u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43mlogger\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdebug\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mError on connect(): \u001b[39;49m\u001b[38;5;132;43;01m%s\u001b[39;49;00m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43me\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 901\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 902\u001b[39m \u001b[38;5;66;03m# in SQLAlchemy 1.4 the first_connect event is not used by\u001b[39;00m\n\u001b[32m 903\u001b[39m \u001b[38;5;66;03m# the engine, so this will usually not be set\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\util\\langhelpers.py:224\u001b[39m, in \u001b[36msafe_reraise.__exit__\u001b[39m\u001b[34m(self, type_, value, traceback)\u001b[39m\n\u001b[32m 222\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exc_value \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 223\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc_value.with_traceback(exc_tb)\n\u001b[32m 225\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 226\u001b[39m \u001b[38;5;28mself\u001b[39m._exc_info = \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;66;03m# remove potential circular references\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\pool\\base.py:895\u001b[39m, in \u001b[36m_ConnectionRecord.__connect\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m 893\u001b[39m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[32m 894\u001b[39m \u001b[38;5;28mself\u001b[39m.starttime = time.time()\n\u001b[32m--> \u001b[39m\u001b[32m895\u001b[39m \u001b[38;5;28mself\u001b[39m.dbapi_connection = connection = \u001b[43mpool\u001b[49m\u001b[43m.\u001b[49m\u001b[43m_invoke_creator\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 896\u001b[39m pool.logger.debug(\u001b[33m\"\u001b[39m\u001b[33mCreated new connection \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[33m\"\u001b[39m, connection)\n\u001b[32m 897\u001b[39m \u001b[38;5;28mself\u001b[39m.fresh = \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\create.py:661\u001b[39m, in \u001b[36mcreate_engine..connect\u001b[39m\u001b[34m(connection_record)\u001b[39m\n\u001b[32m 658\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m connection \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 659\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m connection\n\u001b[32m--> \u001b[39m\u001b[32m661\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mdialect\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\sqlalchemy\\engine\\default.py:629\u001b[39m, in \u001b[36mDefaultDialect.connect\u001b[39m\u001b[34m(self, *cargs, **cparams)\u001b[39m\n\u001b[32m 627\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mconnect\u001b[39m(\u001b[38;5;28mself\u001b[39m, *cargs: Any, **cparams: Any) -> DBAPIConnection:\n\u001b[32m 628\u001b[39m \u001b[38;5;66;03m# inherits the docstring from interfaces.Dialect.connect\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m629\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mloaded_dbapi\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mcparams\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:365\u001b[39m, in \u001b[36mConnection.__init__\u001b[39m\u001b[34m(self, user, password, host, database, unix_socket, port, charset, collation, sql_mode, read_default_file, conv, use_unicode, client_flag, cursorclass, init_command, connect_timeout, read_default_group, autocommit, local_infile, max_allowed_packet, defer_connect, auth_plugin_map, read_timeout, write_timeout, bind_address, binary_prefix, program_name, server_public_key, ssl, ssl_ca, ssl_cert, ssl_disabled, ssl_key, ssl_key_password, ssl_verify_cert, ssl_verify_identity, compress, named_pipe, passwd, db)\u001b[39m\n\u001b[32m 363\u001b[39m \u001b[38;5;28mself\u001b[39m._sock = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m 364\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m--> \u001b[39m\u001b[32m365\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\pymysql\\connections.py:723\u001b[39m, in \u001b[36mConnection.connect\u001b[39m\u001b[34m(self, sock)\u001b[39m\n\u001b[32m 721\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m DEBUG:\n\u001b[32m 722\u001b[39m \u001b[38;5;28mprint\u001b[39m(exc.traceback)\n\u001b[32m--> \u001b[39m\u001b[32m723\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[32m 725\u001b[39m \u001b[38;5;66;03m# If e is neither DatabaseError or IOError, It's a bug.\u001b[39;00m\n\u001b[32m 726\u001b[39m \u001b[38;5;66;03m# But raising AssertionError hides original error.\u001b[39;00m\n\u001b[32m 727\u001b[39m \u001b[38;5;66;03m# So just reraise it.\u001b[39;00m\n\u001b[32m 728\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m\n", + "\u001b[31mOperationalError\u001b[39m: (pymysql.err.OperationalError) (2003, \"Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)\")\n(Background on this error at: https://sqlalche.me/e/20/e3q8)" + ] + } + ], + "source": [ + "#!/usr/bin/env python\n", + "# -*- coding: utf-8 -*-\n", + "\"\"\"\n", + "LAB | Connecting Python to SQL\n", + "Sakila Database - Rental Activity Comparison (May vs June 2005)\n", + "Author: Abhishek Rahul\n", + "\"\"\"\n", + "\n", + "# ============================================================\n", + "# 1. Import Libraries & Establish Connection\n", + "# ============================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "from sqlalchemy import create_engine\n", + "\n", + "# Database connection settings — UPDATE YOUR PASSWORD HERE\n", + "db_user = \"root\"\n", + "db_password = \"Ironhck2025\" # <-- Replace with your MySQL password\n", + "db_host = \"localhost\"\n", + "db_name = \"sakila\"\n", + "\n", + "# Create the connection string and engine\n", + "connection_string = f\"mysql+pymysql://{db_user}:{db_password}@{db_host}/{db_name}\"\n", + "engine = create_engine(connection_string)\n", + "\n", + "print(\"Connection established successfully!\")\n", + "\n", + "# Quick test: verify connection\n", + "test_query = \"SELECT * FROM rental LIMIT 5;\"\n", + "print(pd.read_sql(test_query, engine))\n", + "\n", + "\n", + "# ============================================================\n", + "# 2. Function: rentals_month\n", + "# ============================================================\n", + "\n", + "def rentals_month(engine, month, year):\n", + " \"\"\"\n", + " Retrieves rental data for a specific month and year from the Sakila database.\n", + "\n", + " Parameters:\n", + " -----------\n", + " engine : sqlalchemy.engine.Engine\n", + " Database connection engine for the Sakila database.\n", + " month : int\n", + " Month for which to retrieve rental data (1-12).\n", + " year : int\n", + " Year for which to retrieve rental data.\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " DataFrame containing rental records for the specified month and year.\n", + " \"\"\"\n", + " query = f\"\"\"\n", + " SELECT *\n", + " FROM rental\n", + " WHERE MONTH(rental_date) = {month}\n", + " AND YEAR(rental_date) = {year};\n", + " \"\"\"\n", + "\n", + " rental_data = pd.read_sql(query, engine)\n", + "\n", + " return rental_data\n", + "\n", + "\n", + "# Test: Retrieve rentals for May and June 2005\n", + "may_rentals = rentals_month(engine, 5, 2005)\n", + "print(f\"\\nMay 2005 rentals: {len(may_rentals)} records\")\n", + "print(may_rentals.head())\n", + "\n", + "june_rentals = rentals_month(engine, 6, 2005)\n", + "print(f\"\\nJune 2005 rentals: {len(june_rentals)} records\")\n", + "print(june_rentals.head())\n", + "\n", + "\n", + "# ============================================================\n", + "# 3. Function: rental_count_month\n", + "# ============================================================\n", + "\n", + "def rental_count_month(df, month, year):\n", + " \"\"\"\n", + " Counts the number of rentals per customer for a given month and year.\n", + "\n", + " Parameters:\n", + " -----------\n", + " df : pd.DataFrame\n", + " DataFrame containing rental data (output of rentals_month).\n", + " month : int\n", + " Month used for naming the rental count column.\n", + " year : int\n", + " Year used for naming the rental count column.\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " DataFrame with customer_id and a column named 'rentals_MM_YYYY'\n", + " containing the count of rentals per customer.\n", + " \"\"\"\n", + " # Create the dynamic column name (e.g., 'rentals_05_2005')\n", + " column_name = f\"rentals_{month:02d}_{year}\"\n", + "\n", + " # Group by customer_id and count rentals\n", + " rental_counts = (\n", + " df.groupby(\"customer_id\")\n", + " .agg(rental_count=(\"rental_id\", \"count\"))\n", + " .reset_index()\n", + " .rename(columns={\"rental_count\": column_name})\n", + " )\n", + "\n", + " return rental_counts\n", + "\n", + "\n", + "# Get rental counts for both months\n", + "may_counts = rental_count_month(may_rentals, 5, 2005)\n", + "print(f\"\\nUnique customers in May 2005: {len(may_counts)}\")\n", + "print(may_counts.head(10))\n", + "\n", + "june_counts = rental_count_month(june_rentals, 6, 2005)\n", + "print(f\"\\nUnique customers in June 2005: {len(june_counts)}\")\n", + "print(june_counts.head(10))\n", + "\n", + "\n", + "# ============================================================\n", + "# 4. Function: compare_rentals\n", + "# ============================================================\n", + "\n", + "def compare_rentals(df1, df2):\n", + " \"\"\"\n", + " Compares rental activity between two months by merging the DataFrames\n", + " and calculating the difference in rental counts.\n", + "\n", + " Parameters:\n", + " -----------\n", + " df1 : pd.DataFrame\n", + " First month's rental count DataFrame (output of rental_count_month).\n", + " df2 : pd.DataFrame\n", + " Second month's rental count DataFrame (output of rental_count_month).\n", + "\n", + " Returns:\n", + " --------\n", + " pd.DataFrame\n", + " Combined DataFrame with customer_id, both months' rental counts,\n", + " and a 'difference' column (df2 values - df1 values).\n", + " \"\"\"\n", + " # Merge on customer_id using outer join to include all customers\n", + " combined = df1.merge(df2, on=\"customer_id\", how=\"outer\")\n", + "\n", + " # Fill NaN with 0 (customers active in one month but not the other)\n", + " combined = combined.fillna(0)\n", + "\n", + " # Get the rental count column names (the non-customer_id columns)\n", + " rental_columns = [col for col in combined.columns if col != \"customer_id\"]\n", + "\n", + " # Calculate the difference (second month - first month)\n", + " combined[\"difference\"] = combined[rental_columns[1]] - combined[rental_columns[0]]\n", + "\n", + " return combined\n", + "\n", + "\n", + "# Compare May vs June 2005\n", + "comparison = compare_rentals(may_counts, june_counts)\n", + "print(f\"\\nTotal customers across both months: {len(comparison)}\")\n", + "print(comparison.head(10))\n", + "\n", + "\n", + "# ============================================================\n", + "# 5. Analysis & Insights\n", + "# ============================================================\n", + "\n", + "print(\"\\n\" + \"=\" * 55)\n", + "print(\" RENTAL COMPARISON: MAY vs JUNE 2005\")\n", + "print(\"=\" * 55)\n", + "print(f\" Total customers in May 2005: {len(may_counts)}\")\n", + "print(f\" Total customers in June 2005: {len(june_counts)}\")\n", + "print(f\" Customers active in both: {len(comparison[(comparison['rentals_05_2005'] > 0) & (comparison['rentals_06_2005'] > 0)])}\")\n", + "print(f\" Only active in May: {len(comparison[(comparison['rentals_05_2005'] > 0) & (comparison['rentals_06_2005'] == 0)])}\")\n", + "print(f\" Only active in June: {len(comparison[(comparison['rentals_05_2005'] == 0) & (comparison['rentals_06_2005'] > 0)])}\")\n", + "print(\"-\" * 55)\n", + "print(f\" Avg rentals per customer (May): {comparison['rentals_05_2005'].mean():.2f}\")\n", + "print(f\" Avg rentals per customer (June): {comparison['rentals_06_2005'].mean():.2f}\")\n", + "print(f\" Avg difference (June - May): {comparison['difference'].mean():.2f}\")\n", + "print(\"=\" * 55)\n", + "\n", + "# Customers who rented more in June vs May\n", + "more_in_june = comparison[comparison[\"difference\"] > 0]\n", + "more_in_may = comparison[comparison[\"difference\"] < 0]\n", + "same = comparison[comparison[\"difference\"] == 0]\n", + "\n", + "print(f\"\\nCustomers who rented MORE in June: {len(more_in_june)}\")\n", + "print(f\"Customers who rented MORE in May: {len(more_in_may)}\")\n", + "print(f\"Customers with SAME activity: {len(same)}\")\n", + "\n", + "# Top 10 increases and decreases\n", + "print(\"\\nTop 10 customers with biggest increase (May -> June):\")\n", + "print(comparison.nlargest(10, \"difference\"))\n", + "\n", + "print(\"\\nTop 10 customers with biggest decrease (May -> June):\")\n", + "print(comparison.nsmallest(10, \"difference\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5b50765-1b2c-4e34-9e6c-e7ce04eccd74", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}