- 编程语言
- 语言运行时
- 编译器
- 前端
【免费下载链接】brython
Brython (Browser Python) is an implementation of Python 3 running in the browser
导读
本文聚焦 Brython(浏览器中的 Python 3 实现)提供的两个标准库模块browser.local_storage与browser.session_storage,系统讲解 HTML5 Web Storage 的核心机制、Brython 的字典式封装接口、底层源码实现与典型应用场景。读完本文,你将掌握如何在 Brython 应用中持久化或按会话保存数据、正确处理"键值只能是字符串"这一关键约束,并能基于仓库源码理解每个 API 背后的真实行为与异常规则。
一、HTML5 存储是什么:先理解四个关键事实
Brython 的browser.local_storage模块建立在 HTML5 定义的 Web Storage 规范之上(原始文档引用了 W3C 规范 中关于localStorage属性的定义)。要正确使用它,必须先理解以下四个基础事实:
- 它是浏览器端的客户端键值数据库。数据保存在用户自己的机器上、自己的浏览器里,这也意味着:这些数据只有在用户使用同一台机器、同一个浏览器时才能访问。注意,
local_storage是与浏览器绑定的,而不是与计算机绑定。 - 键(key)和值(value)都必须是字符串。这是最重要的一条约束!例如你存入一个列表,取回时将不是列表,而是它的字符串表示(如
"['a', 'b']")。这一点在原始文档中被特别强调,后文会详细展开。 - 数据按"协议 + 域名 + 端口"隔离。
local_storage数据库归属于一个 HTML5 origin,即三元组scheme://host:port。同一域名的所有页面共享同一个数据库,甚至可以由多个浏览器标签页并发访问;但是,通过http://打开的页面无法看到https://会话期间创建的数据库。 - HTML5 定义了两种存储:本地存储(local storage)与会话存储(session storage)。前者是持久化的,用户关闭浏览器窗口后数据仍然保留;后者在浏览器窗口关闭时即丢失数据。
二、Brython 中的两个模块:local_storage 与 session_storage
HTML5 存储能力在 Brython 中被实现为browser包下的两个模块,对应源码位于 www/src/Lib/browser/local_storage.py 与 www/src/Lib/browser/session_storage.py:
| 模块 | 暴露对象 | 底层 JS 对象 | 生命周期 |
|---|---|---|---|
browser.local_storage | storage | window.localStorage | 持久化,关闭浏览器后数据仍保留 |
browser.session_storage | storage | window.sessionStorage | 会话级,关闭浏览器窗口即丢失 |
两个模块都导出一个名为storage的单一对象,接口完全一致,可以像操作字典一样与之交互(但要牢记键值限于字符串)。
何时该用session_storage?当你不想让数据在浏览器会话或标签页之间共享时使用它——典型场景是登录令牌(log-in token)。原始文档明确指出,会话存储适合存放这类不该跨会话保留的敏感凭证。
从源码看,session_storage的实现非常精简:SessionStorage类直接继承LocalStorage类,只重写了初始化逻辑,将底层的window.localStorage替换为window.sessionStorage,并各自声明了storage_type属性("local_storage"/"session_storage")用于标识类型:
# www/src/Lib/browser/session_storage.py class SessionStorage(LocalStorage): storage_type = "session_storage" def __init__(self): if not has_session_storage: raise EnvironmentError("SessionStorage not available") self.store = window.sessionStorage三、快速上手:读写与删除
原始文档给出的第一个示例即展示了最基本的三行用法:
from browser.local_storage import storage storage['foo'] = 'bar' print(storage['foo']) # 输出: bar执行后,即使你关闭标签页、关闭浏览器甚至关机,只要再次使用同一个浏览器访问同一个scheme://host:port,'foo'键下的值依然可读。
永久删除一个键值对使用del:
del storage['foo'] print(storage['foo']) # 抛出 KeyError删除不存在的键会触发KeyError,这与 Python 字典的行为一致。在源码 www/src/Lib/browser/local_storage.py 中可以看到,__delitem__先检查键必须是字符串,再检查键是否存在于存储中,随后调用底层的removeItem:
def __delitem__(self, key): if not isinstance(key, str): raise TypeError("key must be string") if key not in self: raise KeyError(key) self.store.removeItem(key)四、字典式接口全景:支持的方法与底层行为
storage对象完整模仿了 Python 字典的接口,原始文档列出其支持的方法:
getpopkeysvaluesitemsclear__len____contains____iter__
一个重要的行为差异:keys、values、items返回的是列表拷贝(list copy),而不是字典视图或迭代器。源码中的注释解释了这一设计决策——返回生成器对使用者帮助有限,而自定义迭代器属于过度设计且可能拖慢性能:
def keys(self): return [self.store.key(i) for i in range(self.store.length)] def values(self): return [self.__getitem__(k) for k in self.keys()] def items(self): return list(zip(self.keys(), self.values()))各方法底层实现要点(对照源码)
| 方法/操作 | 底层 JS 调用 | 行为说明 |
|---|---|---|
storage[key] = value | setItem(key, value) | 键或值非字符串时抛TypeError: key/value must be string |
storage[key] | getItem(key) | 命中返回字符串;未命中返回javascript.NULL并抛KeyError(key) |
del storage[key] | removeItem(key) | 键非字符串抛TypeError;键不存在抛KeyError |
key in storage | getItem(key) | 通过返回值是否为javascript.NULL判断存在性 |
len(storage) | store.length | 返回存储中的键值对数量 |
get(key, default=None) | getItem(key) or default | 键不存在时返回默认值 |
pop(key)/pop(key, default) | getItem+removeItem | 无默认值且键不存在时抛KeyError;有默认值则返回默认值 |
clear() | store.clear() | 清空当前 origin 下的全部键值对 |
迭代(__iter__) | 基于keys()列表 | for key in storage可遍历全部键 |
类型检查是硬约束
LocalStorage类对键和值做了严格的类型校验。读写路径上,非字符串的键或值会直接抛出TypeError:
def __setitem__(self, key, value): if not isinstance(key, str): raise TypeError("key must be string") if not isinstance(value, str): raise TypeError("value must be string") self.store.setItem(key, value)这意味着storage[1] = 'x'(整型键)或storage['k'] = 123(整型值)都会失败。如果需要存储列表、字典等结构化数据,请参考第六节的ObjectStorage。
环境可用性检查
两个模块在导入时都会探测浏览器是否支持对应的存储 API。local_storage通过hasattr(window, 'localStorage')检测;session_storage通过hasattr(window, 'sessionStorage')检测。若底层 API 不存在,实例化时会抛出EnvironmentError:
# www/src/Lib/browser/local_storage.py has_local_storage = hasattr(window, 'localStorage') def __init__(self): if not has_local_storage: raise EnvironmentError("LocalStorage not available") self.store = window.localStorage只有探测成功时,模块才会在导入阶段创建storage单例:
if has_local_storage: storage = LocalStorage()五、用测试用例验证接口行为
仓库自带的测试 www/tests/test_storage.py 完整验证了上述接口的行为,可作为学习与回归测试的参考。它依次断言了:
storage.storage_type == "local_storage",sess_storage.storage_type == "session_storage";- 写入与
get读取; pop返回被删除的值,且删除后keys()长度随之变化;pop在键不存在且无默认值时抛KeyError,提供默认值时返回默认值;del删除键值对;for key in storage迭代;items()返回键值对列表。
# 摘自 www/tests/test_storage.py(节选) session_storage['hi'] = "blah" assert(session_storage.get("hi") == "blah") assert(session_storage.pop('foo') == "arg") assert(sorted(session_storage.keys()) == ['hi']) assert(len(session_storage) == 1) del session_storage['hi'] assert(len(session_storage.keys()) == 0)此外,www/tests/index.html 中也有真实页面使用storage["py_src"]保存编辑器源码、用str(doc['files'].selectedIndex)保存下拉选择状态的例子,展示了"值必须是字符串"在实际项目中的处理手法(显式调用str()转换)。
六、进阶:ObjectStorage 让任意对象可存储
由于local_storage原生只接受字符串键值,Brython 在 www/src/Lib/browser/object_storage.py 中提供了ObjectStorage包装类:它利用json.dumps/json.loads在读写前后自动完成序列化与反序列化,从而让字典、列表等任意 JSON 可序列化对象都能直接存入storage:
from browser.object_storage import ObjectStorage from browser.local_storage import storage object_storage = ObjectStorage(local_storage) object_storage['mah'] = {"hi": 5} assert(object_storage['mah'] == {'hi': 5})从源码结构看,ObjectStorage内部将所有键和值统一先json.dumps再写入底层storage,读取时再json.loads还原,因此它同样具备get、pop、keys、values、items、clear、__len__、__contains__、__iter__的完整字典式接口(keys()返回的是反序列化后的键列表)。这也是处理"字符串限制"最直接、最优雅的官方方案。
七、完整示例:基于 local_storage 的 TO-DO 待办应用
原始文档末尾引用了一个完整的实战示例——一个使用local_storage的待办事项(TO-DO list)应用,其完整实现位于 www/doc/en/examples/local_storage/local-storage-example.html。
该示例展示了几个非常实用的模式:
1. 首次访问时初始化存储——用异常捕获判断键是否存在:
try: storage['tasklist'] except: storage['tasklist'] = json.dumps({})2. 用 JSON 序列化保存结构化数据——待办列表整体作为一个 JSON 字符串存进storage['tasklist'],每次增删后调用_save()回写:
self.tasks = json.loads(storage['tasklist']) def _save(self): # 示例中的保存逻辑(示意) storage['tasklist'] = json.dumps(self.tasks)3. 键的生成——用datetime.datetime.now().strftime('%Y/%m/%d-%H:%M:%S')生成时间戳作为每条待办的唯一键,天然规避了"键必须是字符串"的限制。
4. 删除同步——删除任务时同时del self.tasks[key]与del doc[key](移除 DOM 行),再回写存储,保证内存、页面与存储三处一致。
从源码结构看,这个示例还结合了browser.html(html.TR、html.TD、html.IMG动态建表)与事件绑定(link.bind('click', self._del_task)),是"Brython + HTML5 存储 + DOM 操作"的完整闭环样例,适合作为学习模板。
八、使用要点总结
- 字符串约束:键和值只能是字符串,
local_storage/session_storage会在类型不符时抛TypeError;结构化数据请用json手动序列化,或直接使用browser.object_storage的ObjectStorage。 - 作用域隔离:数据归属于
scheme://host:port这一 HTML5 origin,同域名页面共享、跨协议(http/https)隔离。 - 两种生命周期:
local_storage持久化保留;session_storage随浏览器窗口关闭而清空,适合登录令牌等场景。 - 字典式接口:
get、pop、keys、values、items、clear、in、len、del、迭代均可用,但keys/values/items返回列表而非视图。 - 异常行为:读取或删除不存在的键抛
KeyError;pop无默认值时同样抛KeyError;浏览器不支持存储 API 时抛EnvironmentError。 - 官方测试:可参考 www/tests/test_storage.py 验证全部接口行为,该文件同时覆盖了
ObjectStorage的序列化存取。
- 编程语言
- 语言运行时
- 编译器
- 前端
【免费下载链接】brython
Brython (Browser Python) is an implementation of Python 3 running in the browser
相关推荐
Brython 浏览器本地存储指南:browser.local_storage 与 browser.session_storage 完全解析
Brython 浏览器本地存储指南:browser.local_storage 与 browser.session_storage 完全解析 导读 本文围绕 B
编程语言语言运行时编译器前端Kornia 图像工具函数完全指南:make_grid 与形状保持装饰器
Kornia 图像工具函数完全指南:make_grid 与形状保持装饰器 kornia.image 是 Kornia 中面向图像数据的高层 API 模块,而 i
编程语言语言运行时编译器前端Brython 浏览器本地存储实战:使用 browser.local_storage 在浏览器端持久化数据
Brython 浏览器本地存储实战:使用 browser.local_storage 在浏览器端持久化数据 本篇技术指南以 Brython 官方 Cookboo
编程语言语言运行时编译器前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考