不为别的,只为做一个连自己都羡慕的人

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":"参数传递有误!"}) } }

 

posted @ 2022-06-07 17:14  升级打怪  阅读(159)  评论(0编辑  收藏  举报