Python中简单、现代的文件监视和代码重载。
项目描述
watchgod
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 默认由
watch
和awatch
使用,忽略常见的文件如*.swp
、*.pyc
和*~
,以及目录如.git
。 -
PythonWatcher 专门针对 Python 文件,只监视
*.py
、*.pyx
和*.pyd
文件。 -
DefaultDirWatcher 是
DefaultWatcher
和DefaultDirWatcher
的基础。它负责忽略一些常规目录。
如果这些类不足以满足需求,您可以定义自己的监视器,特别是您可能需要重写 should_watch_dir
和 should_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(目前)使用文件轮询而不是操作系统的内置文件更改通知。
这不是疏忽,这是一个有如下理由的决定
- 轮询“足够快”,尤其是在 PEP 471 引入快速
scandir
之后。对于像 TutorCruncher 代码库这样的合理大型项目(有 850 个文件和 300k 行代码),watchgod 可以在大约 24ms 内扫描整个树。以 400ms 的扫描间隔,这大约是 CPU 负载的 5% - 在开发期间完全可接受。 - 标题中就有线索,至少有 4 种不同的文件通知系统需要集成,其中大多数都不简单。这还没有考虑到不同操作系统版本之间的差异。
- 轮询在您想要组合或“去抖动”更改时效果很好。假设您正在运行开发服务器,并在 git 中更改分支,100 个文件发生变化。您是想重新加载开发服务器 100 次还是一次?当然。周期性轮询可能会将这些更改组合成一个事件。如果您正在接收事件流,您需要在接收到第一个事件时延迟重新加载的执行,以查看它是否是文件更改组的一部分。这并不简单。
尽管如此,我可能仍然会使用 rust 的“notify”crate来做文件监视的重工作,参见#25。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。