差分
このページの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' |
| >>> | >>> | ||
| </ | </ | ||