{"id":10158,"date":"2025-09-26T01:49:51","date_gmt":"2025-09-26T09:49:51","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/python\/?p=10158"},"modified":"2025-09-26T01:50:44","modified_gmt":"2025-09-26T09:50:44","slug":"simplifying-resource-management-in-mssql-python-through-context-manager","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/python\/simplifying-resource-management-in-mssql-python-through-context-manager\/","title":{"rendered":"Simplifying Resource Management in mssql-python through Context Manager"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Python_SQL_img.png\"><img decoding=\"async\" class=\" wp-image-10181 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Python_SQL_img-300x152.png\" alt=\"Python SQL img image\" width=\"1074\" height=\"544\" srcset=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Python_SQL_img-300x152.png 300w, https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Python_SQL_img-768x389.png 768w, https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Python_SQL_img.png 1024w\" sizes=\"(max-width: 1074px) 100vw, 1074px\" \/><\/a><\/p>\n<p><em>Reviewed by: Sumit Sarabhai and Gaurav Sharma<\/em><\/p>\n<p>If you\u2019ve worked with databases in Python, you know the boilerplate: open a connection, create a cursor, run queries, commit or rollback transactions, close cursors and connection. Forgetting just one cleanup step can lead to <strong>resource leaks<\/strong> (open connections) or even <strong>inconsistent data<\/strong>. That\u2019s where <strong>context managers<\/strong> step in.<\/p>\n<p>We\u2019ve introduced context manager support in <a href=\"https:\/\/github.com\/microsoft\/mssql-python\"><strong>mssql\u2011python<\/strong><\/a> driver, enabling Python applications to interact with SQL Server and Azure SQL more safely, cleanly, and in a truly Pythonic way.<\/p>\n<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Try it here<\/strong><\/p> You can install driver using <a id=\"menurrq4\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/github.com\/microsoft\/mssql-python\" href=\"https:\/\/pypi.org\/project\/mssql-python\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link pip install mssql-python\"><strong>pip install mssql-python<\/strong><\/a><\/p>\n<p>Calling all Python + SQL developers! We invite the community to try out mssql-python and help us shape the future of high-performance <a id=\"menurrq6\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/github.com\/microsoft\/mssql-python\" href=\"https:\/\/github.com\/microsoft\/mssql-python\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link SQL Server connectivity in Python\">SQL Server connectivity in Python<\/a>.!<\/div><\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Why Context Managers?<\/strong><\/span><\/p>\n<p>In Python, the <code>with<\/code> statement is syntactic sugar for resource management. It actively sets up resources when you enter a block and automatically cleans them up when you exit \u2014 even if an exception is raised.<\/p>\n<p>Think of it as hiring a helper:<\/p>\n<ul>\n<li>They <strong>prepare the workspace<\/strong> before you begin.<\/li>\n<li>They <strong>pack everything up<\/strong> when you\u2019re done.<\/li>\n<li>If something breaks midway, they <strong>handle the cleanup<\/strong> for you.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>The Problem: Managing Connections and Cursors<\/strong><\/span><\/p>\n<p>Earlier, working with Python applications and SQL server\/Azure SQL looked something like this:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">from mssql_python import connect\r\n\r\nconn = connect(connection_string)\r\ncursor = conn.cursor()\r\n\r\ntry:\r\n    cursor.execute(\"SELECT * FROM users\")\r\n    for row in cursor:\r\n        print(row)\r\nfinally:\r\n    cursor.close()\r\n    conn.close()\r\n<\/code><\/pre>\n<p>This works perfectly fine. But imagine if your code had <strong>multiple cursors, multiple queries, and exception handling<\/strong> sprinkled all over. Closing every connection and cursor manually becomes tedious and error-prone. Miss a <code>close()<\/code> somewhere, and you have a resource leak.<\/p>\n<p>That&#8217;s where <strong>Python\u2019s <code>with<\/code> statement<\/strong> \u2014 the context manager \u2014 comes to the rescue. <code>mssql_python<\/code> not only supports it for connections but also for cursors, which makes resource management nearly effortless.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Using Context Managers with Connections<\/strong><\/span><\/p>\n<p>Now comes the real magic \u2014 <strong>connection-level context managers<\/strong>. When you wrap a connection in a <code>with<\/code> block, several things happen under the hood:<\/p>\n<ol>\n<li>If everything succeeds, the transaction is <strong>committed<\/strong>.<\/li>\n<li>If an exception occurs, the transaction is <strong>rolled back<\/strong>.<\/li>\n<li>The connection is always <strong>closed<\/strong> when leaving the block.<\/li>\n<\/ol>\n<p>Example:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">from mssql_python import connect\r\n\r\nwith connect(connection_string) as conn:\r\n    cursor = conn.cursor()\r\n    cursor.execute(\"INSERT INTO users (name) VALUES ('Alice')\")\r\n    # If no exception \u2192 commit happens automatically\r\n    # If exception \u2192 rollback happens automatically\r\n# Connection is closed automatically here<\/code><\/pre>\n<p>Equivalent traditional approach:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">conn = connect(connection_string)\r\ntry:\r\n    cursor = conn.cursor()\r\n    cursor.execute(\"INSERT INTO users (name) VALUES ('Alice')\")\r\n    if not conn.autocommit:\r\n        conn.commit()\r\nexcept:\r\n    if not conn.autocommit:\r\n        conn.rollback()\r\n    raise\r\nfinally:\r\n    conn.close()<\/code><\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>How It Works Internally<\/strong><\/span><\/p>\n<ul>\n<li><span style=\"font-size: 12pt;\"><strong>Entering the block<\/strong><\/span>\n<ul>\n<li>Connection is opened and assigned to conn.<\/li>\n<li>All operations inside the block run using this connection.<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Exiting the block<\/strong><\/span>\n<ul>\n<li><span style=\"font-size: 12pt;\"><strong>No exception:<\/strong><\/span> If <code>autocommit=False<\/code>, transactions are committed.<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Exception raised:<\/strong><\/span> If <code>autocommit=False<\/code>, uncommitted changes are rolled back. The exception propagates unless handled.<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Cleanup:<\/strong> <\/span>Connection is always closed, preventing resource leaks.<\/li>\n<\/ul>\n<p><span style=\"font-size: 14pt;\"><strong>Use case<\/strong>:<\/span> Perfect for transactional code \u2014 inserts, updates, deletes \u2014 where you want automatic commit\/rollback.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Using Context Managers with Cursors<\/strong><\/span><\/p>\n<p>Cursors in <code>mssql_python<\/code> now support the <code>with<\/code> statement. The context here is tied to the <strong>cursor resource<\/strong>, not the transaction.<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with conn.cursor() as cursor:\r\n    cursor.execute(\"SELECT * FROM users\")\r\n    for row in cursor:\r\n        print(row)\r\n# Cursor is automatically closed here<\/code><\/pre>\n<p><span style=\"font-size: 14pt;\"><strong>What happens here?<\/strong><\/span><\/p>\n<ul>\n<li><span style=\"font-size: 12pt;\"><strong>Entering the block<\/strong>:<\/span> A new cursor is created.<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Inside the block<\/strong>:<\/span> All SQL statements execute using this cursor.<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Exiting the block<\/strong>:<\/span> The cursor is automatically closed \u2014 no need to call <code>cursor.close()<\/code> manually.<\/li>\n<li><span style=\"font-size: 12pt;\"><strong>Transactions<\/strong>:<\/span> The cursor itself doesn\u2019t manage transactions. Commit\/rollback is controlled by the connection.\n<ul>\n<li>If <code>autocommit=False<\/code>, changes are committed or rolled back at the connection level.<\/li>\n<li>If <code>autocommit=True<\/code>, each statement is committed immediately as it executes.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Above code is equivalent to the traditional try-finally approach:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">cursor = conn.cursor()\r\ntry:\r\n    cursor.execute(\"SELECT * FROM users\")\r\n    for row in cursor:\r\n        print(row)\r\nfinally:\r\n    cursor.close()<\/code><\/pre>\n<p><span style=\"font-size: 14pt;\"><strong>Use case<\/strong>:<\/span> Best for read-only queries where you don\u2019t want to worry about cursor leaks.<\/p>\n<p><div class=\"alert alert-success\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Lightbulb\"><\/i><strong>Important<\/strong><\/p>If you just want to ensure the cursor closes properly without worrying about transactions, this is the simplest and safest approach.<\/div><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1.png\"><img decoding=\"async\" class=\" wp-image-10166\" src=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1-300x158.png\" alt=\"Context Manager Blog Image\" width=\"885\" height=\"466\" srcset=\"https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1-300x158.png 300w, https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1-1024x539.png 1024w, https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1-768x405.png 768w, https:\/\/devblogs.microsoft.com\/python\/wp-content\/uploads\/sites\/12\/2025\/09\/Screenshot-2025-09-25-230707-1.png 1420w\" sizes=\"(max-width: 885px) 100vw, 885px\" \/><\/a><\/p>\n<p style=\"text-align: center;\">Image 1: Workflow of Context Manager in Connections and Cursor<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Practical Examples<\/strong><\/span><\/p>\n<p><span style=\"font-size: 14pt;\"><strong>Example 1: Safe SELECT Queries<\/strong><\/span><\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with connect(connection_string) as conn:\r\n    with conn.cursor() as cursor:\r\n        cursor.execute(\"SELECT * FROM users WHERE age &gt; 25\")\r\n        for row in cursor:\r\n            print(row)\r\n    # Cursor closed, connection still open until block ends\r\n# Connection is closed    <\/code><\/pre>\n<p><span style=\"font-size: 14pt;\"><strong>Example 2: Multiple Operations in One Transaction<\/strong><\/span><\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with connect(connection_string) as conn:\r\n    with conn.cursor() as cursor:\r\n        cursor.execute(\"INSERT INTO users (name) VALUES ('Bob')\")\r\n        cursor.execute(\"UPDATE users SET age = age + 1 WHERE name = 'Alice'\")\r\n# Everything committed automatically if no exception<\/code><\/pre>\n<p><span style=\"font-size: 14pt;\"><strong>Example 3: Handling Exceptions Automatically<\/strong><\/span><\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">try:\r\n    with connect(connection_string) as conn:\r\n        with conn.cursor() as cursor:\r\n            cursor.execute(\"INSERT INTO users (name) VALUES ('Charlie')\")\r\n            # Simulate error\r\n            raise ValueError(\"Oops, something went wrong\")\r\nexcept ValueError as e:\r\n    print(\"Transaction rolled back due to:\", e)\r\n# Connection closed automatically, rollback executed<\/code><\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Real-Life Scenarios<\/strong><\/span><\/p>\n<p><strong style=\"font-size: 14pt;\"><span style=\"font-size: 14pt;\"><strong>Example 1: <\/strong><\/span>Web Applications<\/strong><\/p>\n<p>In a web app where each request inserts or fetches data:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">def add_user(name):\r\n    with connect(connection_string) as conn:\r\n        with conn.cursor() as cursor:\r\n            cursor.execute(\"INSERT INTO users (name) VALUES (?)\", (name,))<\/code><\/pre>\n<ul>\n<li>Guarantees commit\/rollback automatically.<\/li>\n<li>No open connections piling up.<\/li>\n<li>Clean, readable, and safe code for high-traffic scenarios.<\/li>\n<\/ul>\n<p><strong style=\"font-size: 14pt;\"><span style=\"font-size: 14pt;\"><strong>Example 2: <\/strong><\/span>Data Migration \/ ETL<\/strong><\/p>\n<p>Migrating data between tables:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with connect(connection_string) as conn:\r\n    with conn.cursor() as cursor:\r\n        cursor.execute(\"INSERT INTO archive_users SELECT * FROM users WHERE inactive=1\")\r\n        cursor.execute(\"DELETE FROM users WHERE inactive=1\")<\/code><\/pre>\n<ul>\n<li>If any statement fails, <strong>rollback happens automatically<\/strong>.<\/li>\n<li>Prevents <strong>partial migration<\/strong>, keeping data consistent.<\/li>\n<\/ul>\n<p><strong style=\"font-size: 14pt;\"><span style=\"font-size: 14pt;\"><strong>Example 3: <\/strong><\/span>Automated Reporting<\/strong><\/p>\n<p>Running multiple queries for analytics:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with connect(connection_string) as conn:\r\n    with conn.cursor() as cursor:\r\n        cursor.execute(\"SELECT COUNT(*) FROM users\")\r\n        user_count = cursor.fetchone()[0]\r\n        cursor.execute(\"SELECT department, COUNT(*) FROM employees GROUP BY department\")\r\n        for row in cursor:\r\n            print(row)<\/code><\/pre>\n<ul>\n<li>Cursors closed automatically after each block.<\/li>\n<li>Makes scripts modular and maintainable.<\/li>\n<\/ul>\n<p><strong style=\"font-size: 14pt;\"><span style=\"font-size: 14pt;\"><strong>Example 4: <\/strong><\/span>Financial Transactions<\/strong><\/p>\n<p>Simple bank transfer example:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">def transfer_funds(from_account, to_account, amount):\r\n    with connect(connection_string) as conn:\r\n        with conn.cursor() as cursor:\r\n            cursor.execute(\"UPDATE accounts SET balance = balance - ? WHERE id=?\", (amount, from_account))\r\n            cursor.execute(\"UPDATE accounts SET balance = balance + ? WHERE id=?\", (amount, to_account))<\/code><\/pre>\n<ul>\n<li><strong>Automatic rollback<\/strong> on failure ensures money isn\u2019t lost or double-counted.<\/li>\n<li>Eliminates verbose error-handling boilerplate.<\/li>\n<\/ul>\n<p><strong style=\"font-size: 14pt;\"><span style=\"font-size: 14pt;\"><strong>Example 5: <\/strong><\/span>Ad-Hoc Data Exploration<\/strong><\/p>\n<p>When exploring data in scripts or notebooks:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">with connect(connection_string) as conn:\r\n    with conn.cursor() as cursor:\r\n        cursor.execute(\"SELECT AVG(salary) FROM employees\")\r\n        print(\"Average salary:\", cursor.fetchone()[0])<\/code><\/pre>\n<ul>\n<li>Perfect for quick queries.<\/li>\n<li>No forgotten <code>close()<\/code> calls.<\/li>\n<li>Encourages clean, reusable query blocks.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 18pt;\"><strong>Takeaway <\/strong><\/span><\/p>\n<p>Python\u2019s philosophy is <strong>\u201csimple is better than complex.\u201d<\/strong> With context managers in <code>mssql_python<\/code>, we\u2019ve brought that simplicity to SQL Server interactions with python apps making lives of the developers easier.<\/p>\n<p>Next time you\u2019re working with <code>mssql_python<\/code>, try wrapping your connections and cursors with <code>with<\/code>. You\u2019ll write less code, make fewer mistakes, and your future self will thank you. Whether it\u2019s a high-traffic web application, an ETL script, or exploratory analysis, context managers simplify life, make code safer, and reduce errors.<\/p>\n<p>Remember, context manager will help you with:<\/p>\n<ol>\n<li><strong>Less boilerplate code<\/strong>: No longer try-finally for cursors or connections.<\/li>\n<li><strong>Automatic transaction management<\/strong>: Commit or rollback is handled based on success or failure.<\/li>\n<li><strong>Safe resource cleanup<\/strong>: Prevents resource leaks with automatic closing.<\/li>\n<li><strong>Readable and Pythonic<\/strong>: Nested with blocks clearly show the scope of cursor and connection usage.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p><strong><span style=\"font-size: 18pt;\">Try It and Share Your Feedback!\u00a0<\/span><\/strong><\/p>\n<p>We invite you to:<\/p>\n<ol>\n<li>Check-out the <a id=\"menurrmp\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/github.com\/microsoft\/mssql-python\" href=\"https:\/\/github.com\/microsoft\/mssql-python\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link mssql-python\u00a0\">mssql-python\u00a0<\/a>driver and integrate it into your projects.<\/li>\n<li>Share your thoughts:\u00a0Open <a id=\"menurrmr\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/github.com\/microsoft\/mssql-python\/issues\" href=\"https:\/\/github.com\/microsoft\/mssql-python\/issues\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link issues\">issues<\/a>, suggest features, and contribute to the project.<\/li>\n<li>Join the conversation:\u00a0<a id=\"menurrmt\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/github.com\/microsoft\/mssql-python\/discussions\" href=\"https:\/\/github.com\/microsoft\/mssql-python\/discussions\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link GitHub Discussions\">GitHub Discussions<\/a>\u00a0|\u00a0<a id=\"menurrmv\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/techcommunity.microsoft.com\/category\/sql-server\/blog\/sqlserver\" href=\"https:\/\/techcommunity.microsoft.com\/category\/sql-server\/blog\/sqlserver\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link SQL Server Tech Community\">SQL Server Tech Community<\/a>.<\/li>\n<\/ol>\n<p><div class=\"alert alert-success\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Lightbulb\"><\/i><strong>Use Python Driver with Free Azure SQL Database<\/strong><\/p>You can use the Python Driver with the free version of Azure SQL Database!<\/p>\n<p>\u2705 <a id=\"menurrn1\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/database\/free-offer?view=azuresql\" href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/database\/free-offer?view=azuresql\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link Deploy Azure SQL Database for free\">Deploy Azure SQL Database for free<\/a><\/p>\n<p>\u2705 <a id=\"menurrn3\" class=\"fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn\" title=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/free-offer?view=azuresql\" href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/free-offer?view=azuresql\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Link Deploy Azure SQL Managed Instance for free\">Deploy Azure SQL Managed Instance for free<\/a> Perfect for testing, development, or learning scenarios without incurring costs.<\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reviewed by: Sumit Sarabhai and Gaurav Sharma If you\u2019ve worked with databases in Python, you know the boilerplate: open a connection, create a cursor, run queries, commit or rollback transactions, close cursors and connection. Forgetting just one cleanup step can lead to resource leaks (open connections) or even inconsistent data. That\u2019s where context managers step [&hellip;]<\/p>\n","protected":false},"author":194549,"featured_media":10119,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3,1],"tags":[1277,1281,1283,1282,1278,1280],"class_list":["post-10158","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-python","tag-azure-sql","tag-client-driver","tag-python-driver-for-azure-sql","tag-python-driver-for-sql-server","tag-sql-server","tag-sql-server-2025"],"acf":[],"blog_post_summary":"<p>Reviewed by: Sumit Sarabhai and Gaurav Sharma If you\u2019ve worked with databases in Python, you know the boilerplate: open a connection, create a cursor, run queries, commit or rollback transactions, close cursors and connection. Forgetting just one cleanup step can lead to resource leaks (open connections) or even inconsistent data. That\u2019s where context managers step [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/10158","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/users\/194549"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/comments?post=10158"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/posts\/10158\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media\/10119"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/media?parent=10158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/categories?post=10158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/python\/wp-json\/wp\/v2\/tags?post=10158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}