1
1
<!DOCTYPE html>
2
2
< html lang ="zh-Hant ">
3
+
3
4
< head >
4
5
< meta charset ="UTF-8 ">
5
6
< title > Pyodide Python 執行器</ title >
8
9
font-family : Arial, sans-serif;
9
10
margin : 20px ;
10
11
}
12
+
11
13
textarea {
12
14
width : 100% ;
13
15
height : 200px ;
16
18
padding : 10px ;
17
19
box-sizing : border-box;
18
20
}
21
+
19
22
# output {
20
23
width : 100% ;
21
24
height : 400px ;
26
29
white-space : pre-wrap;
27
30
border : 1px solid # ccc ;
28
31
}
32
+
29
33
button {
30
34
padding : 10px 20px ;
31
35
font-size : 16px ;
32
36
margin-top : 10px ;
33
37
cursor : pointer;
34
38
}
39
+
40
+ # input-container {
41
+ display : none;
42
+ margin : 10px 0 ;
43
+ }
44
+
45
+ # input-box {
46
+ width : 70% ;
47
+ padding : 5px ;
48
+ margin-right : 10px ;
49
+ }
35
50
</ style >
36
51
</ head >
52
+
37
53
< body >
38
54
< h1 > Pyodide Python 執行器</ h1 >
39
- < textarea id ="python-code " placeholder ="在此輸入您的 Python 程式碼,例如: print('Hello, Pyodide!') "> for i in range(3):
40
- user_input = input("請輸入字串")
41
- print(user_input + "!")</ textarea >
55
+ < textarea id ="python-code "> async def main():
56
+ for i in range(2):
57
+ user_input = await input("請輸入字串")
58
+ print(user_input + "$")
59
+
60
+ await main()</ textarea >
42
61
< br >
43
62
< button id ="run-button "> 執行程式碼</ button >
63
+ < div id ="input-container ">
64
+ < input type ="text " id ="input-box ">
65
+ < button id ="input-submit "> 提交</ button >
66
+ </ div >
44
67
< h2 > 輸出結果:</ h2 >
45
68
< div id ="output "> </ div >
46
69
47
- <!-- 加載 Pyodide -->
48
70
< script src ="https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js "> </ script >
49
71
< script >
50
72
let pyodideReadyPromise = loadPyodide ( ) ;
73
+ let inputResolve = null ;
51
74
52
75
async function runPython ( ) {
53
76
let pyodide = await pyodideReadyPromise ;
54
77
let code = document . getElementById ( "python-code" ) . value ;
55
78
let outputElement = document . getElementById ( "output" ) ;
79
+ let inputContainer = document . getElementById ( "input-container" ) ;
80
+
56
81
outputElement . textContent = "" ;
82
+
83
+ // 輸出函數
84
+ function writeOutput ( text ) {
85
+ const p = document . createElement ( 'pre' ) ;
86
+ p . style . margin = '0' ;
87
+ p . textContent = text ;
88
+ outputElement . appendChild ( p ) ;
89
+ outputElement . scrollTop = outputElement . scrollHeight ;
90
+ }
91
+
92
+ // 自定義輸入處理
93
+ async function customInput ( message ) {
94
+ writeOutput ( message ) ;
95
+ inputContainer . style . display = 'block' ;
96
+ document . getElementById ( 'input-box' ) . focus ( ) ;
97
+
98
+ return new Promise ( resolve => {
99
+ inputResolve = resolve ;
100
+ } ) ;
101
+ }
102
+
103
+ // 將函數暴露給 Pyodide
104
+ globalThis . writeOutput = writeOutput ;
105
+ globalThis . customInput = customInput ;
57
106
58
- // 修改输出处理,实现即时显示
59
- let printOutput = ( text ) => {
60
- if ( text && text . trim ( ) ) { // 只处理非空输出
61
- outputElement . textContent += text + "\n" ;
62
- outputElement . scrollTop = outputElement . scrollHeight ;
107
+ // 處理輸入提交
108
+ document . getElementById ( 'input-submit' ) . onclick = ( ) => {
109
+ if ( inputResolve ) {
110
+ const value = document . getElementById ( 'input-box' ) . value ;
111
+ document . getElementById ( 'input-box' ) . value = '' ;
112
+ inputContainer . style . display = 'none' ;
113
+ writeOutput ( value ) ;
114
+ inputResolve ( value ) ;
115
+ inputResolve = null ;
63
116
}
64
117
} ;
65
118
66
- // 将自定义的 prompt 函数添加到全局作用域
67
- globalThis . customPrompt = ( message ) => {
68
- printOutput ( message ) ; // 立即显示输入提示
69
- const result = prompt ( message ) ;
70
- if ( result !== null ) {
71
- printOutput ( result + "!" ) ; // 立即显示用户输入的结果
119
+ // 處理按下 Enter 鍵
120
+ document . getElementById ( 'input-box' ) . onkeypress = ( e ) => {
121
+ if ( e . key === 'Enter' ) {
122
+ document . getElementById ( 'input-submit' ) . click ( ) ;
72
123
}
73
- return result ;
74
124
} ;
75
125
76
- // 修改 Python 的标准输出和错误输出处理
77
- pyodide . setStdout ( {
78
- write : ( text ) => {
79
- printOutput ( text ) ;
80
- } ,
81
- flush : ( ) => { }
82
- } ) ;
83
-
84
- pyodide . setStderr ( {
85
- write : ( text ) => {
86
- printOutput ( text ) ;
87
- } ,
88
- flush : ( ) => { }
89
- } ) ;
90
-
91
- // 修改输入函数实现
126
+ // Python 端設置
92
127
pyodide . runPython ( `
93
- from js import customPrompt
128
+ from js import customInput, writeOutput
94
129
95
- def custom_input(prompt_text=""):
96
- return customPrompt(prompt_text)
97
-
98
- input = custom_input
130
+ async def input(prompt_text=""):
131
+ return await customInput(prompt_text)
132
+
133
+ def print(*args, **kwargs):
134
+ end = kwargs.get('end', '\\n')
135
+ sep = kwargs.get('sep', ' ')
136
+ text = sep.join(str(arg) for arg in args) + end
137
+ writeOutput(text)
99
138
` ) ;
100
139
101
140
try {
102
141
await pyodide . runPythonAsync ( code ) ;
103
142
} catch ( err ) {
104
- printOutput ( err . toString ( ) ) ;
143
+ writeOutput ( "Error: " + err . toString ( ) ) ;
105
144
}
106
145
}
107
146
108
147
document . getElementById ( "run-button" ) . addEventListener ( "click" , runPython ) ;
109
148
</ script >
110
149
</ body >
111
- </ html >
150
+
151
+ </ html >
0 commit comments