微软最近开源了 MarkItDown,这是一个将 Office 文件转换为 Markdown 格式的程序。该项目一发布就迅速登上了 GitHub 的热门榜。
但是,由于 MarkItDown 是一个 Python 程序,因此对于非技术用户来说使用起来可能具有挑战性。为了解决这个问题,我想到了使用WebAssembly技术,直接在浏览器中运行Python代码。
Pyodide 是一个在浏览器中运行 Python 的开源程序,使用 WebAssembly 移植 CPython,因此支持所有 Python 语法。 Cloudflare 的 Python Workers 也使用 Pyodide。
Pyodide 是 CPython 到 WebAssembly/Emscripten 的端口。
Pyodide 使得使用 micropip 在浏览器中安装和运行 Python 包成为可能。支持 PyPI 上可用的任何带轮子的纯 Python 包。
许多带有 C 扩展的软件包也已被移植以与 Pyodide 一起使用。其中包括 regex、PyYAML、lxml 等常见包和 NumPy、pandas、SciPy、Matplotlib 和 scikit-learn 等科学 Python 包。 Pyodide 附带强大的 JavaScript ⟺ Python 外部函数接口,允许您以最小的摩擦在代码中自由地混合这些语言。这包括对错误处理、异步/等待等的全面支持。
在浏览器中使用时,Python 具有对 Web API 的完全访问权限。
尝试运行 MarkItDown 出奇的顺利,证明 WebAssembly 确实是浏览器的未来。
面临的主要挑战和解决方案:
文件传输问题:如何将用户选择的文件传递到 Worker 中的 Python 运行时?
依赖安装问题:中国大陆PyPI访问受限。
最终,我们成功实现了完全在浏览器中运行的 MarkItDown 工具。欢迎在 Office File to Markdown 中尝试一下。
这是在 Worker 中运行 Python 的核心代码:
// eslint-disable-next-line no-undef importScripts('https://testingcf.jsdelivr.net/pyodide/v0.26.4/full/pyodide.js') async function loadPyodideAndPackages() { // eslint-disable-next-line no-undef const pyodide = await loadPyodide() globalThis.pyodide = pyodide await pyodide.loadPackage('micropip') const micropip = pyodide.pyimport('micropip') // micropip.set_index_urls([ // 'https://pypi.your.domains/pypi/simple', // ]) await micropip.install('markitdown==0.0.1a2') } const pyodideReadyPromise = loadPyodideAndPackages() globalThis.onmessage = async (event) => { await pyodideReadyPromise const file = event.data try { console.log('file', file) const startTime = Date.now() globalThis.pyodide.FS.writeFile(`/${file.filename}`, file.buffer) await globalThis.pyodide.runPythonAsync(` from markitdown import MarkItDown markitdown = MarkItDown() result = markitdown.convert("/${file.filename}") print(result.text_content) with open("/${file.filename}.md", "w") as file: file.write(result.text_content) `) globalThis.postMessage({ filename: `${file.filename}.md`, content: globalThis.pyodide.FS.readFile(`/${file.filename}.md`, { encoding: 'utf8' }), time: Date.now() - startTime, }) } catch (error) { globalThis.postMessage({ error: error.message || 'convert error', filename: file.filename }) } }
以上是在浏览器中轻松运行Python程序。的详细内容。更多信息请关注PHP中文网其他相关文章!