- 编程语言
- 语言运行时
- 编译器
- 前端
【免费下载链接】brython
Brython (Browser Python) is an implementation of Python 3 running in the browser
导读
本文基于 Brython 官方 Cookbook 中的 read_file 示例(www/doc/fr/cookbook/read_file.md),系统讲解在浏览器中读取服务器端文件的两种典型方案:使用 Python 内置函数open()同步读取,以及使用browser.ajax模块异步请求并处理超时场景。读完本文,你将掌握两种方案各自的适用场景、反缓存技巧(query string 随机参数)、Ajax 事件绑定与超时处理,并能直接复用文中代码搭建自己的文件读取功能。
问题场景:浏览器中读取文件内容
在纯浏览器环境下,Python 程序没有操作系统级的文件系统可访问,open()不再指向本地磁盘,而是通过 HTTP 请求加载服务器上的静态资源。Brython 的 Cookbook 将"读取一个文件的内容"作为基础问题,给出了两条解决路径:
- 同步方案:直接调用内置函数
open()读取文件内容; - 异步方案:使用
browser.ajax发起 GET 请求,并额外处理文件不存在或响应超时的情况。
两种方案本质都是 HTTP 请求,区别在于 API 形态与对异常场景的覆盖能力。
方案一:用内置 open() 同步读取文件
基础代码
from browser import document import time fake_qs = '?foo=%s' % time.time() document['zone'].value = open('file.txt' + fake_qs).read()对应的 HTML 区域:
<textarea id="zone" rows=10 cols=40>Contenu Initial</textarea>执行流程:
time.time()生成一个时间戳;- 拼出带 query string 的文件名
file.txt?foo=xxx; open(...)通过 HTTP 请求获取文件内容并返回文件对象;- 调用
.read()读取全部文本,写入document['zone'].value(textarea 的值)。
在 Brython 中,open()由标准库 www/src/Lib/_io.py 中的__open(file, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)实现,其参数签名与 CPython 保持一致,支持'r'(默认,只读)、'w'(写入并截断)、'x'(排他创建)、'a'(追加)等模式。Cookbook 示例使用默认的'r'文本只读模式,因此无需显式传入 mode。
关键细节:query string 反缓存
示例中最容易被忽略的是fake_qs = '?foo=%s' % time.time()这一行。它给请求 URL 附加了一个每次都不同的随机参数,作用是绕过浏览器缓存:当服务器上的file.txt内容被修改后,再次调用open()时,URL 因参数不同而被视为新资源,从而强制重新拉取,避免拿到陈旧内容。
这与 www/doc/fr/browser.ajax.md 中cache参数的机制一致——Brython 的 Ajax 模块默认不使用浏览器缓存,并"自动向请求附加一个数字参数"以达到同样的反缓存效果。
方案一的适用边界
open()同步方案代码最简洁,适用于:
- 读取小型文本文件;
- 不关心加载耗时与错误处理;
- 文件确实存在于服务器上(返回 HTTP 200)。
它的局限也很明显:如果文件不存在或请求失败,open()会抛出异常,且同步阻塞期间页面脚本无法继续执行。Cookbook 因此紧接着给出了带超时与错误处理的 Ajax 版本。
方案二:用 browser.ajax 异步读取并处理超时
完整代码
from browser import ajax, document import time def on_complete(req): if req.status == 200 or req.status == 0: document["zone"].value = req.text else: document["zone"].value = "error " + req.text def err_msg(): document["zone"].text = "le serveur n'a pas répondu après %s secondes" % timeout timeout = 4 def go(url): req = ajax.Ajax() req.bind("complete", on_complete) req.set_timeout(timeout, err_msg) req.open('GET', url, True) req.send() go('file.txt?foo=%s' % time.time())逐步拆解
- 创建请求对象:
req = ajax.Ajax()返回一个不带参数的新 Ajax 对象(对应 Web API 的 XMLHttpRequest 封装,见 www/src/libs/_ajax.js)。 - 绑定完成事件:
req.bind("complete", on_complete)把回调函数挂在complete事件上。browser.ajax支持的事件有uninitialized、loading、loaded、interactive、complete五个,实践中一般只关心complete。 - 设置超时:
req.set_timeout(timeout, err_msg)指定在 4 秒内未收到响应则取消请求,并调用不带参数的err_msg()。 - 发起请求:
req.open('GET', url, True)中第三个参数True表示异步(脚本不等待响应,继续执行);req.send()真正发送请求。
回调中的状态判断
on_complete(req)接收请求对象作为唯一参数,通过req.status判断结果:
200:资源成功获取,将req.text写入 textarea;0:本地文件协议等特殊场景下 status 为 0,同样视为成功;- 其他状态码(如 404):拼接
"error " + req.text写入页面。
req.text是响应文本内容(请求模式为"text"时是str实例)。若请求模式为"binary",text则是bytes实例;若为"json",访问text会触发AttributeError,应改用req.json属性(见 www/doc/fr/browser.ajax.md)。
超时处理的执行路径
set_timeout在 www/src/libs/_ajax.js 中实现:超时到达后取消请求并调用注册的回调函数。示例中的err_msg()将提示文案写入document["zone"].text,告知用户"服务器在 N 秒内没有响应"。
注意一个细节:err_msg()中引用的timeout是模块级变量(值为 4),而go()中的req.set_timeout(timeout, err_msg)传入的也是同一个值——若想动态调整超时秒数,只需修改这一处变量即可。
两种方案对比与选型建议
| 维度 | open() 同步方案 | browser.ajax 异步方案 |
|---|---|---|
| API 形态 | 内置函数,与 CPython 一致 | Ajax 对象 + 事件绑定 |
| 阻塞行为 | 同步,脚本等待响应 | 异步,open(..., True)不阻塞 |
| 错误处理 | 异常抛出,需 try/except | 通过req.status分支处理 |
| 超时控制 | 无内置机制 | set_timeout(秒数, 回调) |
| 适用场景 | 小型文本、快速读取 | 大文件、慢网络、需要用户反馈 |
选型建议:简单演示与内部工具页优先用open();面向用户的正式页面、需要展示加载失败或超时提示的场景,务必使用browser.ajax方案。
延伸:browser.ajax 的其他读取模式
browser.ajax模块还提供了更简洁的ajax.get(url, **callbacks)语法,以及mode参数控制响应解析方式(www/doc/fr/browser.ajax.md):
mode="text"(默认):req.text返回str,可用encoding指定编码(如encoding="latin1");mode="binary":req.text/req.read()返回bytes,适合图片等二进制资源;mode="json":req.json返回反序列化后的 JSON 对象;mode="document":req.xml返回 XML 文档树。
例如读取非 UTF-8 编码的文本文件:
from browser import ajax def read(req): print(req.text) ajax.get("test-latin1.txt", encoding="latin1", oncomplete=read)读取二进制文件:
from browser import ajax def read(req): assert isinstance(req.read(), bytes) ajax.get("picture.png", mode="binary", oncomplete=read)读取 JSON:
from browser import ajax def read(req): print(req.json) ajax.get("test.json", mode="json", oncomplete=read)运行前提与限制
- 两种方案都依赖 HTTP 服务:需要将页面与
file.txt通过本地服务器(如仓库根目录的 server.py 或 server_aiohttp.py)托管,直接以file://打开时跨域与缓存行为可能与预期不同。 - 示例中的
file.txt为演示数据(见 www/doc/fr/cookbook/file.txt),实际使用时替换为服务器上真实存在的文件路径。 - 反缓存参数
?foo=时间戳是必要的:若两次请求 URL 完全相同,浏览器可能直接返回缓存的旧内容,导致修改服务器文件后页面看不到更新。 browser.ajax的异步回调中无法捕获常规 Python 异常,错误分支必须通过req.status显式判断;超时则统一由set_timeout的回调处理。
小结
Brython 让 Python 开发者无需接触 JavaScript 即可完成浏览器端的文件读取。open()方案胜在简洁、贴近 CPython 习惯;browser.ajax方案胜在异步、可控、健壮,可覆盖超时与错误状态。两者结合随机 query string 的反缓存技巧,即可应对"服务器文件更新后页面必须同步刷新"的常见需求。若需处理二进制、JSON、XML 等更多响应类型,可直接在browser.ajax的mode参数上扩展,相关细节可在 www/doc/fr/browser.ajax.md 中继续查阅。
- 编程语言
- 语言运行时
- 编译器
- 前端
【免费下载链接】brython
Brython (Browser Python) is an implementation of Python 3 running in the browser
相关推荐
Brython 中读取文件内容的两种实战方案:内建 open() 与 browser.ajax 异步请求
Brython 中读取文件内容的两种实战方案:内建 open 与 browser.ajax 异步请求 导读 :本文基于 Brython 官方 Cookbook
编程语言语言运行时编译器前端在浏览器中读取文件内容:Brython 的 `open()` 与异步 Ajax 双方案实战
在浏览器中读取文件内容:Brython 的 open 与异步 Ajax 双方案实战 导读 在 Brython(浏览器中的 Python 3 实现)中读取服务器上
编程语言语言运行时编译器前端Brython 浏览器端 Ajax 请求实战指南:browser.ajax 模块的双接口用法与源码剖析
Brython 浏览器端 Ajax 请求实战指南:browser.ajax 模块的双接口用法与源码剖析 browser.ajax 是 Brython(运行在浏览
编程语言语言运行时编译器前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考