Golang Web应用与Python脚本的对比与实现

Golang Web应用与Python脚本的对比与实现 我正在使用Go、HTML和CSS创建一个Web应用程序,我想在点击按钮时运行一个Python脚本(.py文件)。我知道这是可能的,所以如果你知道解决方案,请帮助我。是否有相关的教程、示例链接?或者视频也可以,如果有的话会更好。谢谢。

1 回复

更多关于Golang Web应用与Python脚本的对比与实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go Web应用中调用Python脚本,可以通过os/exec包实现。以下是两种实现方式:

方法1:直接执行Python脚本

package main

import (
    "fmt"
    "net/http"
    "os/exec"
    "log"
)

func runPythonScript(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    // 执行Python脚本
    cmd := exec.Command("python3", "path/to/your/script.py", "arg1", "arg2")
    
    // 获取输出
    output, err := cmd.CombinedOutput()
    if err != nil {
        log.Printf("Python脚本执行失败: %v\n", err)
        http.Error(w, fmt.Sprintf("执行失败: %v", err), http.StatusInternalServerError)
        return
    }
    
    fmt.Fprintf(w, "Python脚本输出:\n%s", output)
}

func main() {
    http.HandleFunc("/run-python", runPythonScript)
    http.Handle("/", http.FileServer(http.Dir("./static")))
    
    fmt.Println("服务器启动在 :8080")
    http.ListenAndServe(":8080", nil)
}

方法2:使用goroutine异步执行

package main

import (
    "encoding/json"
    "net/http"
    "os/exec"
    "sync"
    "log"
)

type ScriptResponse struct {
    Status  string `json:"status"`
    Output  string `json:"output,omitempty"`
    Error   string `json:"error,omitempty"`
}

var (
    scriptMutex sync.Mutex
    isRunning   bool
)

func runPythonAsync(w http.ResponseWriter, r *http.Request) {
    scriptMutex.Lock()
    if isRunning {
        scriptMutex.Unlock()
        json.NewEncoder(w).Encode(ScriptResponse{
            Status: "error",
            Error:  "脚本已在运行中",
        })
        return
    }
    isRunning = true
    scriptMutex.Unlock()

    go func() {
        defer func() {
            scriptMutex.Lock()
            isRunning = false
            scriptMutex.Unlock()
        }()

        cmd := exec.Command("python3", "script.py")
        output, err := cmd.CombinedOutput()
        
        if err != nil {
            log.Printf("脚本执行错误: %v\n输出: %s", err, output)
        } else {
            log.Printf("脚本执行成功:\n%s", output)
        }
    }()

    json.NewEncoder(w).Encode(ScriptResponse{
        Status: "started",
        Output: "Python脚本已开始执行",
    })
}

func main() {
    http.HandleFunc("/run-python-async", runPythonAsync)
    http.ListenAndServe(":8080", nil)
}

对应的HTML前端示例

<!DOCTYPE html>
<html>
<head>
    <title>运行Python脚本</title>
    <style>
        button {
            padding: 10px 20px;
            font-size: 16px;
            cursor: pointer;
        }
        #output {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            white-space: pre-wrap;
        }
    </style>
</head>
<body>
    <button onclick="runPythonScript()">运行Python脚本</button>
    <div id="output"></div>

    <script>
        async function runPythonScript() {
            const outputDiv = document.getElementById('output');
            outputDiv.textContent = '执行中...';
            
            try {
                const response = await fetch('/run-python', {
                    method: 'POST'
                });
                
                if (response.ok) {
                    const text = await response.text();
                    outputDiv.textContent = text;
                } else {
                    outputDiv.textContent = '执行失败: ' + response.statusText;
                }
            } catch (error) {
                outputDiv.textContent = '请求失败: ' + error.message;
            }
        }
    </script>
</body>
</html>

Python脚本示例

# script.py
import sys
import json
import time

def main():
    # 获取Go传递的参数
    if len(sys.argv) > 1:
        args = sys.argv[1:]
        print(f"接收到的参数: {args}")
    
    # 模拟处理过程
    print("Python脚本开始执行...")
    time.sleep(2)
    
    result = {
        "status": "success",
        "message": "处理完成",
        "data": [1, 2, 3, 4, 5]
    }
    
    print(json.dumps(result, indent=2))
    return result

if __name__ == "__main__":
    main()

关键注意事项

  1. 路径处理:确保Python脚本路径正确,可使用绝对路径
  2. 环境变量:如果需要特定Python环境,可设置cmd.Env
  3. 超时控制:长时间运行的脚本需要超时机制
  4. 错误处理:检查Python是否安装,脚本是否有执行权限
  5. 安全性:避免用户输入直接传递给exec命令
// 带超时控制的执行
func runWithTimeout() {
    cmd := exec.Command("python3", "script.py")
    
    // 设置10秒超时
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    cmd = exec.CommandContext(ctx, "python3", "script.py")
    output, err := cmd.CombinedOutput()
    
    if ctx.Err() == context.DeadlineExceeded {
        log.Println("脚本执行超时")
    }
}

这种集成方式适用于需要利用Python特定库(如机器学习、数据科学库)的场景,同时保持Go的高性能Web服务能力。

回到顶部