异步代码已成为 Python 开发的支柱。随着 asyncio 成为标准库的一部分,并且许多第三方软件包提供与其兼容的功能,这种范例不会很快消失。
如果您正在编写异步代码,请务必确保代码的所有部分都能协同工作,这样其中的一个方面就不会减慢其他所有部分的速度。文件 I/O 可能是这方面的常见阻碍,因此让我们逐步了解如何使用 aiofiles 库异步处理文件。
从基础开始,这是异步读取文件内容所需的所有代码(在异步函数内):
async with aiofiles.open('filename', mode='r') as f: contents = await f.read() print(contents)
让我们继续深入挖掘。
您可能会听到“异步”、“非阻塞”或“并发”等术语,但对它们的含义感到有点困惑。根据这个更详细的教程,两个主要属性是:
因此,异步代码是可以在等待结果时挂起的代码,以便让其他代码同时运行。它不会“阻止”其他代码运行,因此我们可以将其称为“非阻塞”代码。
asyncio 库为 Python 开发人员提供了多种工具来执行此操作,aiofiles 提供了更具体的文件处理功能。
在我们开始之前,请确保您已设置好 Python 环境。如果您需要帮助,请按照本指南的 virtualenv 部分进行操作。如果您有多个项目在同一台计算机上运行,那么让一切正常工作,特别是在虚拟环境方面,对于隔离依赖项非常重要。 您至少需要 Python 3.7 或更高版本才能运行本文中的代码。
现在您的环境已经设置完毕,您将需要安装一些第三方库。我们将使用 aiofiles,因此在激活虚拟环境后使用以下命令安装它:
pip install aiofiles==0.6.0
对于本文其余部分的示例,我们将使用与原始 150 个 Pokemon 相对应的 Pokemon API 数据的 JSON 文件。您可以在此处下载包含所有这些内容的文件夹。有了这个,您应该准备好继续编写一些代码。
首先,我们简单地打开一个与特定 Pokemon 对应的文件,将其 JSON 解析为字典,并打印出其名称:
async with aiofiles.open('filename', mode='r') as f: contents = await f.read() print(contents)
运行此代码时,您应该看到“articuno”打印到终端。您还可以逐行异步迭代文件(此代码将打印出 articuno.json 的所有 9271 行):
pip install aiofiles==0.6.0
写入文件也类似于标准 Python 文件 I/O。假设我们想要创建包含每个神奇宝贝可以学习的所有动作列表的文件。举个简单的例子,下面是我们对 Pokemon Ditto 所做的事情,它只能学习“变形”这一招式:
import aiofiles import asyncio import json async def main(): async with aiofiles.open('articuno.json', mode='r') as f: contents = await f.read() pokemon = json.loads(contents) print(pokemon['name']) asyncio.run(main())
让我们用一个有不止一个动作的神奇宝贝来尝试一下这个,比如雷顿:
import aiofiles import asyncio async def main(): async with aiofiles.open('articuno.json', mode='r') as f: async for line in f: print(line) asyncio.run(main())
如果您打开 rhydon_moves.txt,您应该会看到一个包含 112 行的文件,其开头类似。
现在让我们变得更复杂一点,对我们拥有 JSON 文件的所有 150 个 Pokemon 执行此操作。我们的代码必须读取每个文件,解析 JSON,并将每个 Pokemon 的动作重写到一个新文件中:
import aiofiles import asyncio async def main(): async with aiofiles.open('ditto_moves.txt', mode='w') as f: await f.write('transform') asyncio.run(main())
运行此代码后,您应该会看到 Pokemon 文件的目录,其中包含 .txt 文件和 .json 文件,其中包含与每个 Pokemon 对应的移动列表。
如果您需要执行一些异步操作,并希望以与这些异步任务相对应的数据结束,例如在写入文件后列出每个 Pokemon 的动作列表,您可以使用 asyncio.ensure_future 和 asyncio.gather。
您可以将处理每个文件的代码部分分解为自己的异步函数,并将这些函数调用的承诺附加到任务列表中。以下是该函数的示例,以及您的新主函数的外观:
import aiofiles import asyncio import json async def main(): # Read the contents of the json file. async with aiofiles.open('rhydon.json', mode='r') as f: contents = await f.read() # Load it into a dictionary and create a list of moves. pokemon = json.loads(contents) name = pokemon['name'] moves = [move['move']['name'] for move in pokemon['moves']] # Open a new file to write the list of moves into. async with aiofiles.open(f'{name}_moves.txt', mode='w') as f: await f.write('\n'.join(moves)) asyncio.run(main())
这是在 Python 中使用异步代码的常见方法,通常用于发出 HTTP 请求之类的事情。
本文中使用 Pokemon 数据的示例只是展示 aiofiles 模块功能以及如何编写代码来导航文件目录以进行读写的借口。希望您可以根据您要解决的特定问题调整这些代码示例,以便文件 I/O 不会成为异步代码中的障碍。
我们只触及了 aiohttp 和 asyncio 功能的皮毛,但我希望这能让您更轻松地开始进入异步 Python 世界。
我期待看到您构建的内容。请随时与我们联系并分享您的经验或提出任何问题。
以上是使用 aiofiles 和 asyncio 在 Python 中异步处理文件的详细内容。更多信息请关注PHP中文网其他相关文章!