go实现jupyter代码的运行
a.go文件
package ws import ( "fallout/common" "fallout/sshed" "fmt" "github.com/gorilla/websocket" "log" "net/http" "strings" ) // ConnWebsocket 连接远端websocket func ConnWebsocket(kernelsId string, authorization string,cookie string, port string) *websocket.Conn { var ip = common.LoadConfig().Learning.Host // ConnWebsocket var addr = flag.String("addr", "127.0.0.1:8887", "http service address") //var addr = flag.String("addr", "192.168.0.121:3839", "http service address") //var addr = flag.String("addr", ip+":"+port, "http service address") //fmt.Println(addr) fmt.Println("确认id是否正确",kernelsId) //u := url.URL{Scheme: "ws", Host: *addr, Path: "/api/kernels/"+kernelsId+"/channels"} //fmt.Println(u) var dialer *websocket.Dialer header := http.Header{ ////"Authorization": []string{"Token 49bb7f981a7cf2647fb22e6095bae531c80a443e69aa6068\n"}, //"Authorization": []string{authorization}, ////"cookie":[]string{"_xsrf=2|5c5e01d3|93bd93516399f1e743638595777ba036|1648890405; username-192-168-0-121-3839=\"2|1:0|10:1650448749|27:username-192-168-0-121-3839|44:NWQ2M2Q2NTdhNDFiNDM4YzgxYTdiMjFkNjA3ZDRiNmY=|8ecf4ce9d9e4804b73c75d761f0ef2124e6ddf373f68699004d6ed2204c5d813\""}, //"cookie":[]string{cookie}, //"X-XSRFToken":[]string{"123"}, "Authorization": []string{common.LoadConfig().Learning.Authorization}, "cookie":[]string{common.LoadConfig().Learning.Cookie}, "X-XSRFToken":[]string{common.LoadConfig().Learning.Xsrftoken}, } //conn, _, err := dialer.Dial(u.String()+"?session_id=6a6af4cc0bde4b50ba4b9518336514ca", header) //conn, _, err := dialer.Dial(u.String(), header) conn, _, err := dialer.Dial("ws://"+ip+":"+port+"/api/kernels/"+kernelsId+"/channels", header) //conn, _, err := dialer.Dial("ws://192.168.0.121:3839/api/kernels/fcb7ef0f-55f6-401e-9818-d907b0337149/channels", header) if err != nil { log.Println(err) return nil }else{ log.Println("链接成功!") } return conn } // ReceiveNews 接收数据 func ReceiveNews(conn *websocket.Conn, path string,username string,kernelId string) { //读取某个文件的内容 //fmt.Println(aa["cells"]) aa :=common.ReadFileCon(path) connMyWebsocket :=ConnMyWebsocket(username) var status ="" cells := aa["cells"].([]interface{}) for key,value :=range cells{ cellValue := value.(map[string]interface{}) if cellValue["cell_type"]=="code" { for { _, message, err := conn.ReadMessage() log.Printf("received: %s\n", message) if err != nil { //fmt.Println("read:", err) log.Println("read:", err) return } con,_:= common.JsonToMap(string(message)) fmt.Println("1111111111111111111111111111111111111122222222222222") fmt.Println(con["msg_type"]) content:=con["content"].(map[string]interface{}) //代表程序开始运行 if con["msg_type"]=="execute_input"{ executionCount, ok:=content["execution_count"] if ok { cells[key].(map[string]interface{})["executionCount"] = executionCount } } //代表程序运行结束 if con["msg_type"]=="execute_reply"{ stus := content["status"] if stus=="ok"{ //代表单元格程序正常执行成功 fmt.Println(stus) break }else if stus!="error" { //如果不等于ok得时候,退出双层循环 status="aborted" status = stus.(string) break }else{ fmt.Println("content error") data := map[string] interface{}{"ename": content["ename"], "evalue": content["evalue"], "output_type": con["status"], "traceback":content["traceback"]} //append追加之后还需要接收 outputs :=append(cells[key].(map[string]interface{})["outputs"].([]interface{}),data) cells[key].(map[string]interface{})["outputs"]=outputs break } } //当内核重启时,结束运行 if con["msg_type"]=="status"{ //restarting 退出双层循环 //fmt.Println(con["content"]) //["execution_count"] ////execution_count := con["content"]["execution_count"] executionState,_:=content["execution_state"] if executionState == "restarting"{ status = content["execution_state"].(string) info:=map[string]interface{}{"username":username, "message":"内核重启!"} SendNewsClient(connMyWebsocket, common.MapToJson(info)) break } } if con["msg_type"] == "error"{ fmt.Println( con["msg_type"]) data := map[string] interface{}{"ename": content["ename"], "evalue": content["evalue"], "output_type": con["msg_type"], "traceback":content["traceback"]} //append追加之后还需要接收 outputs :=append(cells[key].(map[string]interface{})["outputs"].([]interface{}),data) cells[key].(map[string]interface{})["outputs"]=outputs break } //# 返回程序得运行结果 if con["msg_type"] == "stream"{//strip().strip("\b").strip("\r").strip() obj :=map[string] interface{}{"name":content["name"],"output_type": con["msg_type"], "text": [1]string{strings.Trim(content["text"].(string),"\b")}} //append追加之后还需要接收 outputs :=append(cells[key].(map[string]interface{})["outputs"].([]interface {}),obj) cells[key].(map[string]interface{})["outputs"]=outputs } //返回程序得运行结果 图片之类的 if con["msg_type"] == "display_data"{ data :=map[string]interface{}{"metadata": con["metadata"], "data": map[string] interface{}{"text/plain":[1]string{content["data"].(map[string]interface{})["text/plain"].(string)}, "image/png": content["data"].(map[string]interface{})["image/png"].(string)}, "output_type": con["msg_type"]} //append追加之后还需要接收 cells[key].(map[string]interface{})["outputs"]=append(cells[key].(map[string]interface{})["outputs"].([]interface {}),data) } //# print(con["content"]["text"]) //fmt.Printf("received: %s\n", message) //将消息转发给前台 //SendNewsClient(connMyWebsocket, string(message)) //log.Println(reflect.TypeOf(message)) } if status!="" { break } } } //关闭连接 conn.Close() //程序运行结束之后,关闭对应的内核 closeRs := sshed.CloseSingleKernel(kernelId) fmt.Println(closeRs) //将运行结果写入对应的运行结果文件中 rs:= common.WriteFileCon(path,common.MapToJson(aa)) fmt.Println(rs) path=strings.Replace(path,".","",1) path=strings.Replace(path,".ipynb","(运行).ipynb",1) info:=map[string]interface{}{"username":username,"path":path, "message":"已经运行结束!"} } // TimeWriter 推送数据 func TimeWriter(conn *websocket.Conn,sendData string) { //fmt.Println("//////////////////////////////") //fmt.Println(sendData) //time.Sleep(time.Second * 5) err:=conn.WriteMessage( websocket.TextMessage, []byte(sendData), ) if err != nil { log.Println("write:", err) return } //for { // //time.Sleep(time.Second * 5) // //conn.WriteMessage(websocket.TextMessage, []byte(time.Now().Format("2006-01-02 15:04:05"))) // encodeInfo,_ :=json.Marshal(&msg) // conn.WriteMessage(websocket.TextMessage, encodeInfo) //} }
main.go文件
package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"fallout/common"
"fallout/sshed"
"fallout/ws"
"fmt"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path"
"reflect"
"strconv"
"strings"
"time"
)
func main() {
r := gin.Default()
//加载模版文件
r.Use(static.Serve("/", static.LocalFile("templates/*.html", true)))
// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
//r.MaxMultipartMemory = 8 << 20 // 8 MiB
r.GET("/runCode",RunCodeHandler)
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "Main website",
})
})
err :=r.Run(":1234")
if err!=nil{
fmt.Println("error")
}
}
func RunCodeHandler(c *gin.Context){ username := c.Query("username") port :=c.Query("port") // 教学端用户使用的端接口号是3839,科研端的是端口号加1 fileName :=c.Query("filename") if username!="" && port!="" &&fileName!="" { //这两个参数必传 authorization :=common.LoadConfig().Learning.Authorization cookie:=common.LoadConfig().Learning.Cookie var base = "http://"+common.LoadConfig().Minio.Host+":"+port var url = base + "/api/kernels" fmt.Println(base) body,_ :=common.GetThirdData("POST",url, "") resId,err :=common.JsonToMap(body) if message,ok:=resId["message"];ok { c.JSON(http.StatusOK, gin.H{"status": 3, "message": message}) }else{ if err!=nil{ c.JSON(http.StatusOK, gin.H{"status": 2, "message":err}) }else{ _id:=resId["id"].(string) fmt.Println("kernelsID",_id) //fmt.Println(reflect.TypeOf(_id)) //var notebookPath ="/home/jupyter/tf2/入门神经网络.ipynb" var notebookPath =common.LoadConfig().Learning.Targetpath+fileName //var base = "http://192.168.0.121:8089" var conUrl = base + "/api/contents"+ notebookPath fmt.Println("1233555") fmt.Println(conUrl) body1,_:=common.GetThirdData("GET",conUrl, "") aa, er :=common.JsonToMap(body1) //fmt.Println(er) if er!=nil{ fmt.Println(reflect.TypeOf(er)) c.JSON(http.StatusOK, gin.H{"status": 2, "message":er}) }else{ cells1,ok1 :=aa["content"] if ok1 { //2. 启动对应文件接收运行结果消息 conn := ws.ConnWebsocket(_id, authorization,cookie, port) if conn != nil { localpath :="./dataset/algorithm/"+fileName go ws.ReceiveNews(conn, localpath,username,_id) //3. 获取运行文件的代码并进行解析 cells :=cells1.(map[string]interface{})["cells"].([]interface{}) //将数据转为数组对象类型 ul:=strings.Replace(uuid.NewV4().String(), "-", "", -1) fmt.Println(ul) for _, value := range cells { //go生成uuid //ul:=strings.Replace(uuid.NewV4().String(), "-", "", -1) //fmt.Println(ul) //根据当前时间,将本地时间转为指定格式 currTime :=time.Now().UTC().Format("2006-01-02 15:04:05") local, _ := time.LoadLocation("Local") rfc, _ := time.ParseInLocation("2006-01-02 15:04:05", currTime, local) hdr :=common.Hdr{ MsgId: ul, Username:username, Session: ul, Data:rfc, MsgType:"execute_request", Version:"5.0", } cellValue := value.(map[string]interface{}) //将数据转为map类型,其中"."后面的括号里面的代表强转 if cellValue["cell_type"]=="code"{ simpleCode := cellValue["source"] content :=common.Content{ Code: simpleCode.(string), Silent: false, } msg:=common.Msg{ Header:&hdr, ParentHeader:&hdr, Metadata: make(map[string]interface{}), Content:&content, } encodeInfo,_ :=json.Marshal(msg) ws.TimeWriter(conn, string(encodeInfo)) } //break } //conn.Close() //返回json结果 c.JSON(http.StatusOK, gin.H{"status": 1, "message":"程序正在运行中。。。。。。"}) }else{ c.JSON(http.StatusOK, gin.H{"status": 3, "message":"运行出现异常!"}) } }else{ c.JSON(http.StatusOK, gin.H{"status": 2, "message":aa["message"]}) } } } } }else{ c.JSON(http.StatusOK, gin.H{"status": -1, "message":"参数传递有误!"}) } }