Pyodide环境可通过检测window.pyodide存在且为对象,或sys.platform=="emscripten"来可靠识别;需同时排除Electron、Node.js等干扰环境,避免仅依赖window或sys.implementation.name。
window 和 pyodide 全局对象是否存在Pyodide 运行在浏览器 Web Worker 或主线程中,会向全局作用域注入 window(或 self)和 pyodide 对象。最直接的判断方式是检测这两个标识符是否可访问且类型正确:
window 存在且为 object(排除 Node.js 或纯 CLI 环境)window.pyodide 存在且为对象(不是 undefined 或 null)window —— 比如 Electron、NW.js 也有 window,但不是 Pyodide实操建议:
def is_pyodide():
try:
import sys
if "pyodide" in sys.modules:
return True
# fallback: check global JS scope
from js import window
return hasattr(window, "pyodide") and window.pyodide is not None
except (ImportError, Att
ributeError):
return False
sys.platform 和 sys.implementation.name 辅助识别Pyodide 的 sys.platform 固定为 "emscripten",sys.implementation.name 是 "cpython"(注意:不是 "pyodide"),这点和 CPython 本体不同但和 Emscripten 编译目标一致。
sys.platform == "emscripten" 是强信号,几乎只出现在 Pyodide / Emscripten 环境sys.implementation.name == "cpython" 不可靠 —— 标准 CPython 也返回这个值sys.platform == "emscripten" + "pyodide" in sys.modules
有些环境也会暴露 window 或模拟浏览器 API,导致简单判断出错:
window,但没有 pyodide 对象window,渲染进程有 window 但无 pyodide
globalThis.window 是 undefined,但某些 polyfill 库可能挂载空对象因此必须把 pyodide 对象存在性作为必要条件,而不是仅靠运行时平台字符串或全局变量名。
综合上述,一个低侵入、不抛异常、兼容导入时机的检测方式:
def is_pyodide():
try:
from js import window
if hasattr(window, "pyodide") and window.pyodide:
return True
except ImportError:
pass
try:
import sys
if sys.platform == "emscripten":
return True
except AttributeError:
pass
return False
注意:该函数在非浏览器环境(如本地 Python)中不会触发 js 模块导入失败以外的副作用;is_pyodide() 返回 True 时,基本可以安全调用 pyodide.loadPackage 或读取 js.document —— 但别忘了,js 模块本身只在 Pyodide 初始化完成后才可用,所以首次检测最好放在 main() 或事件回调中,而非模块顶层。