差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
python:pyodide [2022/10/11 10:25] – [インストール] ともやん | python:pyodide [2024/06/27 12:22] (現在) – [Pyodide - Web ブラウザで動作する Python 環境] ともやん | ||
---|---|---|---|
行 2: | 行 2: | ||
<script src=" | <script src=" | ||
<link href=" | <link href=" | ||
- | <link href="/ | + | |
< | < | ||
#terminal { | #terminal { | ||
行 15: | 行 15: | ||
< | < | ||
self.startTime = new Date(); | self.startTime = new Date(); | ||
- | self.languagePluginUrl = '/ | + | |
</ | </ | ||
- | <script src="/ | + | <script src="/ |
< | < | ||
- | jQuery(function() { | + | |
+ | function sleep(s) { | ||
+ | return new Promise((resolve) => setTimeout(resolve, | ||
+ | } | ||
+ | |||
+ | async function main() { | ||
+ | let term; | ||
+ | globalThis.pyodide = await loadPyodide({ | ||
+ | stdin: () => { | ||
+ | let result = prompt(); | ||
+ | echo(result); | ||
+ | return result; | ||
+ | }, | ||
+ | }); | ||
+ | let namespace = pyodide.globals.get(" | ||
+ | pyodide.runPython( | ||
+ | ` | ||
+ | import sys | ||
+ | import pyodide | ||
+ | from pyodide.ffi import to_js | ||
+ | from pyodide.console import PyodideConsole, | ||
+ | import __main__ | ||
+ | BANNER = " | ||
+ | pyconsole = PyodideConsole(__main__.__dict__) | ||
+ | import builtins | ||
+ | async def await_fut(fut): | ||
+ | res = await fut | ||
+ | if res is not None: | ||
+ | builtins._ = res | ||
+ | return to_js([res], | ||
+ | def clear_console(): | ||
+ | pyconsole.buffer = [] | ||
+ | `, | ||
+ | { globals: namespace }, | ||
+ | ); | ||
+ | let repr_shorten = namespace.get(" | ||
+ | let banner = namespace.get(" | ||
+ | let await_fut = namespace.get(" | ||
+ | let pyconsole = namespace.get(" | ||
+ | let clear_console = namespace.get(" | ||
+ | const echo = (msg, ...opts) => | ||
+ | term.echo( | ||
+ | msg | ||
+ | .replaceAll(" | ||
+ | .replaceAll(" | ||
+ | ...opts, | ||
+ | ); | ||
+ | namespace.destroy(); | ||
+ | |||
+ | let ps1 = ">>> | ||
+ | ps2 = "... "; | ||
+ | |||
+ | async function lock() { | ||
+ | let resolve; | ||
+ | let ready = term.ready; | ||
+ | term.ready = new Promise((res) => (resolve = res)); | ||
+ | await ready; | ||
+ | return resolve; | ||
+ | } | ||
+ | |||
+ | async function interpreter(command) { | ||
+ | let unlock = await lock(); | ||
+ | term.pause(); | ||
+ | // multiline should be split (useful when pasting) | ||
+ | for (const c of command.split(" | ||
+ | let fut = pyconsole.push(c); | ||
+ | term.set_prompt(fut.syntax_check === " | ||
+ | switch (fut.syntax_check) { | ||
+ | case " | ||
+ | term.error(fut.formatted_error.trimEnd()); | ||
+ | continue; | ||
+ | case " | ||
+ | continue; | ||
+ | case " | ||
+ | break; | ||
+ | default: | ||
+ | throw new Error(`Unexpected type ${ty}`); | ||
+ | } | ||
+ | // In JavaScript, await automatically also awaits any results of | ||
+ | // awaits, so if an async function returns a future, it will await | ||
+ | // the inner future too. This is not what we want so we | ||
+ | // temporarily put it into a list to protect it. | ||
+ | let wrapped = await_fut(fut); | ||
+ | // complete case, get result / error and print it. | ||
+ | try { | ||
+ | let [value] = await wrapped; | ||
+ | if (value !== undefined) { | ||
+ | echo( | ||
+ | repr_shorten.callKwargs(value, | ||
+ | separator: " | ||
+ | }), | ||
+ | ); | ||
+ | } | ||
+ | if (pyodide.isPyProxy(value)) { | ||
+ | value.destroy(); | ||
+ | } | ||
+ | } catch (e) { | ||
+ | if (e.constructor.name === " | ||
+ | const message = fut.formatted_error || e.message; | ||
+ | term.error(message.trimEnd()); | ||
+ | } else { | ||
+ | throw e; | ||
+ | } | ||
+ | } finally { | ||
+ | fut.destroy(); | ||
+ | wrapped.destroy(); | ||
+ | } | ||
+ | } | ||
+ | term.resume(); | ||
+ | await sleep(10); | ||
+ | unlock(); | ||
+ | } | ||
+ | |||
+ | term = jQuery("# | ||
+ | term.text('' | ||
+ | self.endTime = new Date(); | ||
+ | var ms = self.endTime.getTime() - self.startTime.getTime(); | ||
+ | banner = " | ||
+ | term.terminal(interpreter, | ||
+ | greetings: banner, | ||
+ | prompt: ps1, | ||
+ | completionEscape: | ||
+ | completion: function (command, callback) { | ||
+ | callback(pyconsole.complete(command).toJs()[0]); | ||
+ | }, | ||
+ | keymap: { | ||
+ | " | ||
+ | clear_console(); | ||
+ | term.enter(); | ||
+ | echo(" | ||
+ | term.set_command("" | ||
+ | term.set_prompt(ps1); | ||
+ | }, | ||
+ | TAB: (event, original) => { | ||
+ | const command = term.before_cursor(); | ||
+ | // Disable completion for whitespaces. | ||
+ | if (command.trim() === "" | ||
+ | term.insert(" | ||
+ | return false; | ||
+ | } | ||
+ | return original(event); | ||
+ | }, | ||
+ | }, | ||
+ | }); | ||
+ | window.term = term; | ||
+ | pyconsole.stdout_callback = (s) => echo(s, { newline: false }); | ||
+ | pyconsole.stderr_callback = (s) => { | ||
+ | term.error(s.trimEnd()); | ||
+ | }; | ||
+ | term.ready = Promise.resolve(); | ||
+ | pyodide._api.on_fatal = async (e) => { | ||
+ | term.error( | ||
+ | " | ||
+ | ); | ||
+ | term.error(" | ||
+ | term.error(e); | ||
+ | term.error(" | ||
+ | await term.ready; | ||
+ | term.pause(); | ||
+ | await sleep(15); | ||
+ | term.pause(); | ||
+ | }; | ||
+ | |||
+ | const searchParams = new URLSearchParams(window.location.search); | ||
+ | if (searchParams.has(" | ||
+ | $(" | ||
+ | } | ||
+ | } | ||
+ | window.console_ready = main(); | ||
+ | /*jQuery(function() { | ||
languagePluginLoader.then(() => { | languagePluginLoader.then(() => { | ||
function pushCode(line) { | function pushCode(line) { | ||
行 90: | 行 259: | ||
} | } | ||
}); | }); | ||
- | }); | + | });*/ |
</ | </ | ||
</ | </ | ||
行 99: | 行 268: | ||
Web ブラウザ上で Python 言語および Python のデータサイエンスライブラリ (NumPy, Scipy, Pandas, Matplotlib... など[[https:// | Web ブラウザ上で Python 言語および Python のデータサイエンスライブラリ (NumPy, Scipy, Pandas, Matplotlib... など[[https:// | ||
**Pyodide** は [[https:// | **Pyodide** は [[https:// | ||
+ | |||
+ | ===== 関連プロジェクト ===== | ||
+ | [[https:// | ||
+ | [[https:// | ||
===== コンソール ====== | ===== コンソール ====== | ||
行 108: | 行 281: | ||
>>> | >>> | ||
>>> | >>> | ||
- | 3.7.0 (default, Dec 11 2019, 12:37:21) | + | '3.10.2 (main, Sep 25 2022, 05:41:13) [Clang |
- | [Clang | + | |
>>> | >>> | ||
- | 3,7,0,final,0 | + | sys.version_info(major=3, minor=10, micro=2, releaselevel=' |
>>> | >>> | ||
>>> | >>> | ||
- | Emscripten | + | 'Emscripten' |
>>> | >>> | ||
- | Emscripten-1.0-x86-JS-32bit | + | 'Emscripten-3.1.21-wasm32-32bit' |
>>> | >>> | ||
</ | </ |