开发在线编程网站
前言
初學者學習編程語言時,通常需要安裝編程語言對應的環境,以Python為例,要學習Python,你就需要下載Python解釋器并安裝到本地,對于沒有編程經驗的人而言,這一步難倒了很多人,所以很多編程學習網站提供了在線編程的功能,學習者可以在網站上直接編寫Python代碼,然后點擊運行,便可以在網頁中得到相應的結果,這是怎么做到的?
最近剛好在做直播任務,即每周要做一定量的抖音直播,昨日直播時,臨時起意,打算實現這個功能并將查資料、研究、開發的過程作為直播內容,開播時,我也不知道自己能不能弄出來,但因為剛做直播沒多久,沒啥人看,也就沒啥包袱,直接開整,最后還是讓我弄出來了。
本篇文章就記錄一下開發過程。
前端開發
經過簡單的調研,放棄一開始想用Vue3開發的想法,直接使用HTML、CSS、JS搞則可,再上個Jquery,來使用Ajax,大體的流程為:
Code?=>?Ajax?=>?Python?Web(Flask)?=>?Run?Code?=>?Result代碼通過Ajax發給后端服務(Flask構建),不同編程語言使用不同的解釋器去執行相應的代碼,將執行的結果返回。
創建online-ide的目錄,在目錄下,構建如下結構:
C:\USERS\ADMIN\WORKPLACE\ONLINE-IDE ├─back-end├─serve.py └─front-end├─ide.html├─css└─style.css├─js└─ide.js└─libfront-end用于放前端代碼,back-end用于放后端代碼,我們將頁面的主代碼寫到ide.html中,代碼非常簡單,就是用div構建不同的部分,然后用css簡單修飾一下:
<!DOCTYPE?html> <html?lang="en"> <head><meta?charset="UTF-8"><meta?http-equiv="X-UA-Compatible"?content="IE=edge"><meta?name="viewport"?content="width=device-width,?initial-scale=1.0"><title>Online?IDE</title><!--?<link?rel="stylesheet"?href="css/style.css"/>?--><link?rel="stylesheet"?href="front-end/css/style.css"> </head> <body><div?class="header">?Online?IDE?</div><div?class="control-panel"><!--?選擇編程語言?-->選擇編程語言: <select?name="languages"?id="languages"?class="languages"?onchange="changeLanguage()"><option?value="c">C</option><option?value="cpp">C++</option><option?value="nodejs">Node.js</option><option?value="python">Python</option></select></div><div?class="editor"?id="editor"><!--?編寫代碼的地方?--></div><div?class="button-container"><!--?點擊按鈕,運行代碼?--><button?class="btn"?onclick="runCode()">?運行?</button></div><div?class="output"><!--?代碼結果輸出?--></div> </body> </html>代碼中有相應的注釋,就不贅述了。
這里有個核心就是前端要有代碼編輯區域,單純的div是無法滿足代碼編輯需求的,比如代碼高亮,簡單的語法報錯等,通過簡單搜索,發現ace(https://github.com/ajaxorg/ace)這個項目,該項目通過JS實現了支持代碼高亮的代碼編輯器。
閱讀ace的文檔發現項目作者提供了打包好的版本ace-builds(https://github.com/ajaxorg/ace-builds/),我們可以直接使用。
通過git clone拉取ace-builds項目,然后將src中的所有代碼文件都賦值front-end/lib中,這些就是不同編程語言對應著其中的文件。
獲取了ace后,我們還需要使用它,在ide.js中,我們寫入如下代碼:
let?editor;window.onload?=?function()?{//?載入aceeditor?=?ace.edit("editor");//?設置編輯器主題editor.setTheme("ace/theme/monokai");//?設置編輯器解析的編程語言editor.session.setMode("ace/mode/c_cpp");}//?選擇不同編程語言時,需要切換ace的modefunction?changeLanguage()?{let?language?=?$("#languages").val();if?(language?==?'c'?||?language?==?'cpp')?{editor.session.setMode("ace/mode/c_cpp");}?else?if?(language?==?'python'){editor.session.setMode("ace/mode/python");}else?if?(language?==?'nodejs'){editor.session.setMode("ace/mode/javascript");};}//?用戶寫完代碼,點擊運行時,將代碼通過Ajax發送至Python后端function?runCode()?{$.ajax({url:?"/run_code",method:?"POST",data:?{language:?$("#languages").val(),code:?editor.getSession().getValue()},success:?function(response)?{console.log('success');console.log(response);$('.output').text(response);}})}至此,前端就開發完了。
后端開發
后端我選擇Flask來開發,非常快,直接基于Flask docs里提供的代碼,復制粘貼,再修修改改則可,我們將代碼寫到back-end的serve.py中,代碼如下:
import?subprocess import?os import?time from?flask?import?Flask from?flask?import?render_template from?flask?import?requesttemplate_dir?=?os.path.abspath("../front-end") static_folder?=?os.path.abspath("../front-end") app?=?Flask(__name__,?static_folder=static_folder,?template_folder=template_dir)@app.route("/run_code",??methods=['GET',?'POST']) def?run_code():if?request.method?==?'POST':"""1.接收到前端信息2.將其存入文件中3.使用相關的解釋器去執行文件中的代碼4.將執行的結果返回給前端"""code?=?request.values.get('code')language?=?request.values.get('language')code_file_path?=?os.path.join(os.path.abspath('codes'))?+?str(time.time())?+?'.code'with?open(code_file_path,?'w')?as?f:f.write(code)if?language?==?'python':py_path?=?'c:\\users\\admin\\appdata\\local\\programs\\python\\python38\\python.exe'process?=?subprocess.Popen([py_path,?code_file_path],stdout=subprocess.PIPE,stderr=subprocess.PIPE)stdout,?stderr?=?process.communicate()output?=?stdout?+?stderrelif?language?==?'nodejs':node_path?=?r'C:\Program?Files\nodejs\node.exe'process?=?subprocess.Popen([node_path,?code_file_path],stdout=subprocess.PIPE,stderr=subprocess.PIPE)stdout,?stderr?=?process.communicate()output?=?stdout?+?stderrreturn?outputelif?request.method?==?'GET':return?render_template("ide.html",?name="run?code")if?__name__?==?"__main__":app.run(port=8001)上述代碼沒啥難度,就是設置了一個run_code接口,如果是GET請求,則返回HTML頁面(ide.html),如果是POST,則按編程語言的類型選擇相應的解釋器,去執行相應的代碼。
通過Python的subprocess,利用shell的形式執行代碼。
效果
運行項目,先用Python來實現斐波那契數列,效果如下:
換成JavaScript來實現斐波那契數列,效果如下:
結尾
哦豁,實現下來,比我想象的簡單,整個直播的過程對我來說有點像限時編程,播完后,有點累,但感覺開發出來挺爽的。
Enjoy Code,我們下篇文章見。
總結
- 上一篇: 03.获取网页源代码
- 下一篇: 多媒体_音乐播放器