跳转到主要内容

Python中简单、现代的文件监视和代码重载。

项目描述

watchgod

CI Coverage pypi license

Python中简单、现代的文件监视和代码重载。


注意 - 包名已更改为 watchfiles

请注意: 此包(watchgod)已重命名为 watchfiles。请将 watchgod 替换为 watchfiles,有关切换的帮助和说明,请参阅迁移指南

除了更好的名字外,watchfiles 还有一个全新的基于 rust-notify 的后端,这使得监视文件系统事件更加高效。

名为 watchgod 的包将不再开发,并且只会收到关键的安全修复。


用法

监视目录中的更改

from watchgod import watch

for changes in watch('./path/to/dir'):
    print(changes)

运行函数并在代码更改时重启它

from watchgod import run_process

def foobar(a, b, c):
    ...

run_process('./path/to/dir', foobar, args=(1, 2, 3))

run_process 使用 PythonWatcher,因此只有Python文件的更改会触发重载,请参阅下方的 自定义监视器

如果您需要关于更改事件的警报以及重启进程,可以使用 callback 参数传递一个函数,该函数将在每次文件更改时被调用,并带有一个参数:文件更改的集合。

安装

pip install watchgod

异步方法

watchgod 包含了 watch 的异步等效函数:awatch,它使用 ThreadPoolExecutor 来遍历文件。

import asyncio
from watchgod import awatch

async def main():
    async for changes in awatch('/path/to/dir'):
        print(changes)

asyncio.run(main())

同时还有 run_process 的异步等效函数:arun_process,它又使用 awatch

import asyncio
from watchgod import arun_process

def foobar(a, b, c):
    ...

async def main():
    await arun_process('./path/to/dir', foobar, args=(1, 2, 3))

asyncio.run(main())

arun_process 使用 PythonWatcher,因此只有 Python 文件的变化会触发重新加载,详见下文的 自定义监视器

arun_process 的签名几乎与 run_process 相同,区别在于可选的 callback 参数必须是一个协程,而不是一个函数。

自定义监视器

watchgod 包含以下监视器类,可以通过上述方法的 watcher_cls 关键字参数使用。

例如

for changes in watch(directoryin, watcher_cls=RegExpWatcher, watcher_kwargs=dict(re_files=r'^.*(\.mp3)$')):
   print (changes)

更多详细信息,请查看 watcher.py,它相当简单。

  • AllWatcher 基础监视器,检查所有文件的变化。

  • DefaultWatcher 默认由 watchawatch 使用,忽略常见的文件如 *.swp*.pyc*~,以及目录如 .git

  • PythonWatcher 专门针对 Python 文件,只监视 *.py*.pyx*.pyd 文件。

  • DefaultDirWatcherDefaultWatcherDefaultDirWatcher 的基础。它负责忽略一些常规目录。

如果这些类不足以满足需求,您可以定义自己的监视器,特别是您可能需要重写 should_watch_dirshould_watch_file 方法。除非您正在做非常特殊的事情,否则您可能希望从 DefaultDirWatcher 继承。

请注意,与 目录 相关的事件不会被报告(例如,创建目录),但新目录中的新文件将被报告。

命令行界面(CLI)

watchgod 还提供用于运行和重新加载 Python 代码的命令行界面。

假设您有一个 foobar.py 文件。

from aiohttp import web

async def handle(request):
    return web.Response(text='testing')

app = web.Application()
app.router.add_get('/', handle)

def main():
    web.run_app(app, port=8000)

您可以使用以下命令运行它,并在当前目录中的任何文件发生变化时重新加载它:

watchgod foobar.main

如果您需要忽略某些文件或目录,可以使用 --ignore-paths 参数。

运行 watchgod --help 以获取更多选项。您还可以通过 python -m watchgod ...watchgod 作为 Python 可执行模块使用。

为什么没有 inotify / kqueue / fsevent / winapi 支持

watchgod(目前)使用文件轮询而不是操作系统的内置文件更改通知。

这不是疏忽,这是一个有如下理由的决定

  1. 轮询“足够快”,尤其是在 PEP 471 引入快速 scandir 之后。对于像 TutorCruncher 代码库这样的合理大型项目(有 850 个文件和 300k 行代码),watchgod 可以在大约 24ms 内扫描整个树。以 400ms 的扫描间隔,这大约是 CPU 负载的 5% - 在开发期间完全可接受。
  2. 标题中就有线索,至少有 4 种不同的文件通知系统需要集成,其中大多数都不简单。这还没有考虑到不同操作系统版本之间的差异。
  3. 轮询在您想要组合或“去抖动”更改时效果很好。假设您正在运行开发服务器,并在 git 中更改分支,100 个文件发生变化。您是想重新加载开发服务器 100 次还是一次?当然。周期性轮询可能会将这些更改组合成一个事件。如果您正在接收事件流,您需要在接收到第一个事件时延迟重新加载的执行,以查看它是否是文件更改组的一部分。这并不简单。

尽管如此,我可能仍然会使用 rust 的“notify”crate来做文件监视的重工作,参见#25

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源代码分发

watchgod-0.8.2.tar.gz (13.9 kB 查看哈希值)

上传时间 源代码

构建分发

watchgod-0.8.2-py3-none-any.whl (12.3 kB 查看哈希值)

上传时间 Python 3

支持