Skip to content

Commit

Permalink
Reuse Python runtime in the same response
Browse files Browse the repository at this point in the history
  • Loading branch information
bclswl0827 committed Feb 5, 2024
1 parent 49d8436 commit 3fb4da0
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 32 deletions.
49 changes: 29 additions & 20 deletions src/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,26 @@ import userDebounce from "../helpers/userDebounce";
import { Point } from "unist";
import { isObjectEqual } from "../helpers/isObjectEqual";
import { getPythonResult } from "../helpers/getPythonResult";
import { loadPyodide } from "pyodide";
import { getPythonRuntime } from "../helpers/getPythonRuntime";

interface MarkdownProps {
readonly className?: string;
readonly typingEffect: string;
readonly children: string;
}

const RunnerResultPlaceholder = `
😈 [Info] 结果需以 print 输出
🚀 [Info] 尝试执行 Python 脚本...
`;

export const Markdown = (props: MarkdownProps) => {
const { className, typingEffect, children } = props;

const [pythonRuntime, setPythonRuntime] = useState<ReturnType<
typeof loadPyodide
> | null>(null);
const [pythonResult, setPythonResult] = useState<{
result: string;
startPos: Point | null;
Expand All @@ -43,38 +53,37 @@ export const Markdown = (props: MarkdownProps) => {
1200
);

const handleRunnerResult = (x: string) =>
setPythonResult((prev) => ({
...prev,
result: `${prev.result.replace(RunnerResultPlaceholder, "")}\n${x}`,
}));

const handleRunPython = userDebounce(
async (
startPos: Point | null,
endPos: Point | null,
code: string,
currentTarget: EventTarget
) => {
const resultPlaceholder = `
😈 [Info] 结果需以 print 输出
🚀 [Info] 尝试执行 Python 脚本...
`;
let runtime: ReturnType<typeof loadPyodide> | null;
if (pythonRuntime) {
runtime = pythonRuntime;
} else {
runtime = getPythonRuntime(
`${window.location.pathname}pyodide/`,
handleRunnerResult,
handleRunnerResult
);
setPythonRuntime(runtime);
}
(currentTarget as HTMLButtonElement).disabled = true;
setPythonResult({
result: `$ python3 script.py${resultPlaceholder}`,
result: `$ python3 script.py${RunnerResultPlaceholder}`,
startPos,
endPos,
});
const handler = (x: string) =>
setPythonResult((prev) => ({
...prev,
result: `${prev.result.replace(
resultPlaceholder,
""
)}\n${x}`,
}));
await getPythonResult(
code,
`${window.location.pathname}pyodide/`,
handler,
handler,
handler
);
await getPythonResult(runtime, code, handleRunnerResult);
(currentTarget as HTMLButtonElement).disabled = false;
},
300
Expand Down
18 changes: 6 additions & 12 deletions src/helpers/getPythonResult.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { loadPyodide } from "pyodide";

export const getPythonResult = async (
pyodide: ReturnType<typeof loadPyodide>,
code: string,
repoURL: string,
onStdout: (x: string) => void,
onStderr: (x: string) => void,
onException: (x: string) => void
) => {
const availablePackages = [
Expand All @@ -25,12 +23,6 @@ export const getPythonResult = async (
{ keyword: "hashlib", package: "hashlib" },
];
try {
const pyodide = await loadPyodide({
indexURL: repoURL,
stdout: onStdout,
stderr: onStderr,
homedir: "/home/user",
});
const matchedPackages = availablePackages
.filter(
({ keyword }) =>
Expand All @@ -39,15 +31,17 @@ export const getPythonResult = async (
)
.map(({ package: pkg }) => pkg);
if (!!matchedPackages.length) {
await pyodide.loadPackage(matchedPackages);
await (await pyodide).loadPackage(matchedPackages);
}
await pyodide.runPythonAsync(`
await (
await pyodide
).runPythonAsync(`
from js import prompt
def input(p):
return prompt(p)
__builtins__.input = input
`);
await pyodide.runPythonAsync(code);
await (await pyodide).runPythonAsync(code);
} catch (e) {
onException(`${e}`);
}
Expand Down
13 changes: 13 additions & 0 deletions src/helpers/getPythonRuntime.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { loadPyodide } from "pyodide";

export const getPythonRuntime = (
repoURL: string,
onStdout: (x: string) => void,
onStderr: (x: string) => void
) =>
loadPyodide({
indexURL: repoURL,
stdout: onStdout,
stderr: onStderr,
homedir: "/home/user",
});

0 comments on commit 3fb4da0

Please sign in to comment.