原文:
www.kdnuggets.com/3-interesting-uses-of-python-context-managers
图片来源 Freepik 的 johnstocker
前一段时间,我写了一篇关于 编写高效 Python 代码 的教程。在其中,我讨论了如何使用上下文管理器和 with 语句高效地管理资源。
1. 谷歌网络安全证书 - 快速进入网络安全职业道路。
2. 谷歌数据分析专业证书 - 提升您的数据分析技能
3. 谷歌 IT 支持专业证书 - 支持您的组织进行 IT 工作
我使用了一个简单的文件处理示例,展示了当执行退出 with 块时,文件会被自动关闭——即使发生了异常。
虽然文件处理是一个很好的初步示例,但它很快会变得乏味。这就是为什么我想在本教程中介绍其他有趣的上下文管理器用法——超越文件处理。我们将重点讲解处理数据库连接、管理子进程以及高精度浮点运算。
Python 中的上下文管理器使你在处理资源时能够编写更简洁的代码。它们通过以下方式提供了设置和拆除资源的简洁语法:
-
一个进入逻辑,当执行进入上下文时会被调用
-
一个退出逻辑,当执行退出上下文时会被调用
最简单的示例是文件处理。在这里,我们在 with
语句中使用 open()
函数来获取文件处理器:
with open('filename.txt', 'w') as file:
file.write('Something random')
这会获取资源——文件对象——在代码块中使用(我们写入文件)。当执行退出上下文时,文件会被关闭;因此不会有资源泄漏。
你可以像这样编写通用版本:
with some_context() as ctx:
# do something useful on the resource!
# resource cleanup is automatic
现在让我们继续看具体的示例。
当你构建 Python 应用程序时,连接到数据库并查询它们包含的表是相当常见的。执行此操作的工作流程如下:
-
安装数据库连接器以便与数据库配合使用(例如用于 Postgres 的 psycopg2 和用于 MySQL 数据库的 mysql-connector-python)。
-
解析配置文件以检索连接参数。
-
使用
connect()
函数建立与数据库的连接。
连接到数据库 | 图片来自作者
一旦你连接到数据库,你可以创建一个数据库来查询数据库。运行查询并使用 run 和 fetch 游标方法获取查询结果。
查询数据库 | 图片来自作者
这样,你创建了以下资源:一个数据库连接和一个数据库游标。现在让我们编写一个简单的通用示例,看看如何将连接和游标对象用作上下文管理器。
考虑一个示例 TOML 文件,例如 db_config.toml,包含连接数据库所需的信息:
# db_config.toml
[database]
host = "localhost"
port = 5432
database_name = "your_database_name"
user = "your_username"
password = "your_password"
注意:你需要 Python 3.11 或更高版本才能使用 tomllib。
Python 有一个内置的 tomllib 模块(在 Python 3.11 中引入),可以让你解析 TOML 文件。因此,你可以打开 db_config.toml 文件并像这样解析其内容:
import tomllib
with open('db_config.toml','rb') as file:
credentials = tomllib.load(file)['database']
注意,我们访问了 db_config.toml 文件中的 ‘database’ 部分。load()
函数返回一个 Python 字典。你可以通过打印 credentials
的内容来验证这一点:
print(credentials)
Output >>>
{'host': 'localhost', 'port': 5432, 'database_name': 'your_database_name', 'user': 'your_username', 'password': 'your_password'}
假设你想连接到一个 Postgres 数据库。你可以使用 pip 安装 psycopg2 连接器:
pip install psycopg2
你可以像这样在 with
语句中使用连接和游标对象:
import psycopg2
# Connect to the database
with psycopg2.connect(**credentials) as conn:
# Inside this context, the connection is open and managed
with conn.cursor() as cur:
# Inside this context, the cursor is open and managed
cur.execute('SELECT * FROM my_table')
result = cur.fetchall()
print(result)
在这段代码中:
-
我们使用
with
语句来创建一个管理数据库连接的上下文。 -
在这个上下文中,我们创建了另一个上下文来管理数据库游标。游标在退出这个内部上下文时会自动关闭。
-
由于在退出外部上下文时连接也会被关闭,这种构造确保了连接和游标都得到正确管理——减少了资源泄漏的可能性。
在处理 SQLite 和 MySQL 数据库时,你也可以使用类似的构造。
Python 的 subprocess 模块提供了在 Python 脚本中运行外部命令的功能。subprocess.Popen()
构造函数创建一个新的子进程。你可以在 with
语句中像这样使用它:
import subprocess
# Run an external command and capture its output
with subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, text=True) as process:
output, _ = process.communicate()
print(output)
在这里,我们运行 Bash 命令 ls -l
来长列表显示当前目录中的文件:
Output >>>
total 4
-rw-rw-r-- 1 balapriya balapriya 0 Jan 5 18:31 db_info.toml
-rw-rw-r-- 1 balapriya balapriya 267 Jan 5 18:32 main.py
一旦退出 with
语句的上下文,子进程相关的资源会被释放。
Python 中的内置 float 数据类型不适合高精度浮点运算。但在处理财务数据、传感器读数等时,你确实需要高精度。对于这种应用,你可以使用 decimal 模块。
localcontext()
函数 返回一个上下文管理器。因此,你可以在 with
语句中使用 localcontext()
函数,并按如下方式设置当前上下文的精度:
from decimal import Decimal, localcontext
with localcontext() as cur_context:
cur_context.prec = 40
a = Decimal(2)
b = Decimal(3)
print(a/b)
输出如下:
Output >>>
0.6666666666666666666666666666666666666667
在这里,精度设置为 40 位小数——但仅在当前 with
块内。当执行退出当前上下文时,精度将恢复为默认精度(28 位小数)。
在本教程中,我们学习了如何使用上下文管理器处理数据库连接、管理子进程以及在高精度浮点运算中的上下文。
在下一节教程中,我们将探讨如何在 Python 中创建自定义上下文管理器。在此之前,祝编程愉快!
Bala Priya C是来自印度的开发者和技术作家。她喜欢在数学、编程、数据科学和内容创作的交汇处工作。她的兴趣和专长领域包括 DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编程和喝咖啡!目前,她正致力于通过撰写教程、使用指南、评论文章等方式学习并与开发者社区分享她的知识。Bala 还创建了引人入胜的资源概述和编程教程。