C# WinForms程序調(diào)用Python腳本的完整代碼案例
C# 上位機(jī)調(diào)用 Python 腳本的完整案例
下面是一個(gè)完整的 C# WinForms 應(yīng)用程序,通過下拉框選擇不同的 Python 腳本并執(zhí)行。
1. 項(xiàng)目結(jié)構(gòu)
PythonCallerApp/ ├── PythonScripts/ # Python 腳本目錄 │ ├── script1.py │ ├── script2.py │ └── script3.py ├── Form1.cs # 主窗體 ├── Form1.Designer.cs └── Program.cs
2. Python 腳本準(zhǔn)備
首先創(chuàng)建幾個(gè)測試用的 Python 腳本:
script1.py - 簡單的數(shù)學(xué)計(jì)算
import sys
import json
def main():
# 接收參數(shù)
if len(sys.argv) > 1:
try:
data = json.loads(sys.argv[1])
number = data.get('number', 10)
except:
number = 10
else:
number = 10
result = number * 2
output = {
"original_number": number,
"doubled": result,
"message": "數(shù)字已成功翻倍"
}
print(json.dumps(output))
if __name__ == "__main__":
main()
script2.py - 字符串處理
import sys
import json
def main():
if len(sys.argv) > 1:
try:
data = json.loads(sys.argv[1])
text = data.get('text', 'Hello')
repeat = data.get('repeat', 3)
except:
text = 'Hello'
repeat = 3
else:
text = 'Hello'
repeat = 3
result = text * repeat
output = {
"original_text": text,
"repeated": result,
"repeat_count": repeat
}
print(json.dumps(output))
if __name__ == "__main__":
main()
script3.py - 列表處理
import sys
import json
def main():
if len(sys.argv) > 1:
try:
data = json.loads(sys.argv[1])
numbers = data.get('numbers', [1, 2, 3, 4, 5])
except:
numbers = [1, 2, 3, 4, 5]
else:
numbers = [1, 2, 3, 4, 5]
total = sum(numbers)
average = total / len(numbers) if numbers else 0
output = {
"numbers": numbers,
"sum": total,
"average": average,
"count": len(numbers)
}
print(json.dumps(output))
if __name__ == "__main__":
main()
3. C# WinForms 應(yīng)用程序
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Text.Json;
namespace PythonCallerApp
{
public partial class Form1 : Form
{
// Python 腳本目錄
private string pythonScriptsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PythonScripts");
// Python 執(zhí)行器路徑(根據(jù)你的環(huán)境修改)
private string pythonExecutable = "python"; // 或者完整路徑如 @"C:\Python39\python.exe"
public Form1()
{
InitializeComponent();
InitializeComboBox();
}
private void InitializeComboBox()
{
// 清空下拉框
comboBoxScripts.Items.Clear();
// 添加腳本選項(xiàng)
comboBoxScripts.Items.Add(new ScriptItem("數(shù)字翻倍", "script1.py"));
comboBoxScripts.Items.Add(new ScriptItem("文本重復(fù)", "script2.py"));
comboBoxScripts.Items.Add(new ScriptItem("數(shù)字統(tǒng)計(jì)", "script3.py"));
// 設(shè)置顯示屬性
comboBoxScripts.DisplayMember = "DisplayName";
comboBoxScripts.ValueMember = "ScriptName";
// 默認(rèn)選擇第一項(xiàng)
if (comboBoxScripts.Items.Count > 0)
comboBoxScripts.SelectedIndex = 0;
}
private async void btnExecute_Click(object sender, EventArgs e)
{
if (comboBoxScripts.SelectedItem == null)
{
MessageBox.Show("請選擇一個(gè)Python腳本!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var selectedScript = comboBoxScripts.SelectedItem as ScriptItem;
if (selectedScript == null) return;
// 顯示執(zhí)行狀態(tài)
lblStatus.Text = "執(zhí)行中...";
lblStatus.ForeColor = Color.Blue;
btnExecute.Enabled = false;
try
{
string scriptPath = Path.Combine(pythonScriptsPath, selectedScript.ScriptName);
if (!File.Exists(scriptPath))
{
MessageBox.Show($"找不到腳本文件: {scriptPath}", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 準(zhǔn)備參數(shù)
string arguments = PrepareArguments(selectedScript.ScriptName);
// 創(chuàng)建進(jìn)程啟動(dòng)信息
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = pythonExecutable,
Arguments = $"\"{scriptPath}\" {arguments}",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8
};
// 執(zhí)行 Python 腳本
using (Process process = new Process())
{
process.StartInfo = startInfo;
// 收集輸出
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
process.OutputDataReceived += (s, args) => {
if (!string.IsNullOrEmpty(args.Data))
output.AppendLine(args.Data);
};
process.ErrorDataReceived += (s, args) => {
if (!string.IsNullOrEmpty(args.Data))
error.AppendLine(args.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
// 等待進(jìn)程完成(帶超時(shí))
bool completed = process.WaitForExit(30000); // 30秒超時(shí)
if (!completed)
{
process.Kill();
throw new TimeoutException("Python腳本執(zhí)行超時(shí)");
}
// 處理結(jié)果
if (process.ExitCode == 0)
{
string result = output.ToString().Trim();
if (!string.IsNullOrEmpty(result))
{
try
{
// 嘗試解析 JSON 輸出
using JsonDocument doc = JsonDocument.Parse(result);
txtOutput.Text = JsonSerializer.Serialize(doc, new JsonSerializerOptions { WriteIndented = true });
lblStatus.Text = "執(zhí)行成功!";
lblStatus.ForeColor = Color.Green;
}
catch
{
// 如果不是 JSON,直接顯示原始輸出
txtOutput.Text = result;
lblStatus.Text = "執(zhí)行完成!";
lblStatus.ForeColor = Color.Green;
}
}
else
{
txtOutput.Text = "腳本執(zhí)行成功,但無輸出。";
lblStatus.Text = "執(zhí)行完成!";
lblStatus.ForeColor = Color.Green;
}
}
else
{
string errorMessage = error.ToString();
if (string.IsNullOrEmpty(errorMessage))
errorMessage = output.ToString();
txtOutput.Text = $"執(zhí)行失敗 (退出代碼: {process.ExitCode}):\n{errorMessage}";
lblStatus.Text = "執(zhí)行失?。?;
lblStatus.ForeColor = Color.Red;
}
}
}
catch (Exception ex)
{
txtOutput.Text = $"發(fā)生錯(cuò)誤: {ex.Message}";
lblStatus.Text = "執(zhí)行錯(cuò)誤!";
lblStatus.ForeColor = Color.Red;
}
finally
{
btnExecute.Enabled = true;
}
}
private string PrepareArguments(string scriptName)
{
// 根據(jù)不同的腳本準(zhǔn)備不同的參數(shù)
var parameters = new Dictionary<string, object>();
switch (scriptName.ToLower())
{
case "script1.py":
parameters["number"] = 25;
break;
case "script2.py":
parameters["text"] = "Hello Python! ";
parameters["repeat"] = 3;
break;
case "script3.py":
parameters["numbers"] = new List<int> { 10, 20, 30, 40, 50 };
break;
default:
parameters["message"] = "Hello from C#";
break;
}
return JsonSerializer.Serialize(parameters);
}
private void btnOpenScriptDir_Click(object sender, EventArgs e)
{
// 打開腳本目錄
if (Directory.Exists(pythonScriptsPath))
{
Process.Start("explorer.exe", pythonScriptsPath);
}
else
{
MessageBox.Show($"腳本目錄不存在: {pythonScriptsPath}", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 腳本項(xiàng)類
public class ScriptItem
{
public string DisplayName { get; set; }
public string ScriptName { get; set; }
public ScriptItem(string displayName, string scriptName)
{
DisplayName = displayName;
ScriptName = scriptName;
}
public override string ToString()
{
return DisplayName;
}
}
}
Form1.Designer.cs
namespace PythonCallerApp
{
partial class Form1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.comboBoxScripts = new System.Windows.Forms.ComboBox();
this.btnExecute = new System.Windows.Forms.Button();
this.txtOutput = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.lblStatus = new System.Windows.Forms.Label();
this.btnOpenScriptDir = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// comboBoxScripts
//
this.comboBoxScripts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxScripts.FormattingEnabled = true;
this.comboBoxScripts.Location = new System.Drawing.Point(12, 12);
this.comboBoxScripts.Name = "comboBoxScripts";
this.comboBoxScripts.Size = new System.Drawing.Size(200, 23);
this.comboBoxScripts.TabIndex = 0;
//
// btnExecute
//
this.btnExecute.Location = new System.Drawing.Point(218, 12);
this.btnExecute.Name = "btnExecute";
this.btnExecute.Size = new System.Drawing.Size(75, 23);
this.btnExecute.TabIndex = 1;
this.btnExecute.Text = "執(zhí)行腳本";
this.btnExecute.UseVisualStyleBackColor = true;
this.btnExecute.Click += new System.EventHandler(this.btnExecute_Click);
//
// txtOutput
//
this.txtOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtOutput.Location = new System.Drawing.Point(12, 70);
this.txtOutput.Multiline = true;
this.txtOutput.Name = "txtOutput";
this.txtOutput.ReadOnly = true;
this.txtOutput.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtOutput.Size = new System.Drawing.Size(560, 319);
this.txtOutput.TabIndex = 2;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 52);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(68, 15);
this.label1.TabIndex = 3;
this.label1.Text = "執(zhí)行結(jié)果:";
//
// lblStatus
//
this.lblStatus.AutoSize = true;
this.lblStatus.Location = new System.Drawing.Point(299, 16);
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(55, 15);
this.lblStatus.TabIndex = 4;
this.lblStatus.Text = "就緒狀態(tài)";
//
// btnOpenScriptDir
//
this.btnOpenScriptDir.Location = new System.Drawing.Point(497, 12);
this.btnOpenScriptDir.Name = "btnOpenScriptDir";
this.btnOpenScriptDir.Size = new System.Drawing.Size(75, 23);
this.btnOpenScriptDir.TabIndex = 5;
this.btnOpenScriptDir.Text = "打開目錄";
this.btnOpenScriptDir.UseVisualStyleBackColor = true;
this.btnOpenScriptDir.Click += new System.EventHandler(this.btnOpenScriptDir_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(584, 401);
this.Controls.Add(this.btnOpenScriptDir);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.label1);
this.Controls.Add(this.txtOutput);
this.Controls.Add(this.btnExecute);
this.Controls.Add(this.comboBoxScripts);
this.MinimumSize = new System.Drawing.Size(600, 440);
this.Name = "Form1";
this.Text = "Python 腳本調(diào)用器";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private ComboBox comboBoxScripts;
private Button btnExecute;
private TextBox txtOutput;
private Label label1;
private Label lblStatus;
private Button btnOpenScriptDir;
}
}
Program.cs
using System;
using System.Windows.Forms;
namespace PythonCallerApp
{
internal static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
4. 使用說明
環(huán)境要求
- .NET Framework 4.7.2+ 或 .NET 5/6/7/8
- Python 3.6+ 已安裝并添加到 PATH 環(huán)境變量
- 所需的 Python 包:json(標(biāo)準(zhǔn)庫,無需額外安裝)
配置說明
Python 路徑配置:在 Form1.cs 中修改 pythonExecutable 變量
- 如果 Python 已在 PATH 中,使用
"python" - 否則使用完整路徑,如
@"C:\Python39\python.exe"
腳本目錄:確保 PythonScripts 目錄與可執(zhí)行文件在同一目錄
功能特點(diǎn)
- 通過下拉框選擇不同的 Python 腳本
- 實(shí)時(shí)顯示執(zhí)行狀態(tài)
- 支持 JSON 格式的參數(shù)傳遞和結(jié)果解析
- 錯(cuò)誤處理和超時(shí)控制
- 可打開腳本目錄進(jìn)行管理
擴(kuò)展建議
- 添加參數(shù)輸入界面,讓用戶可以自定義輸入?yún)?shù)
- 添加腳本執(zhí)行日志記錄
- 支持批量執(zhí)行多個(gè)腳本
- 添加 Python 環(huán)境檢測功能
- 支持虛擬環(huán)境
以上就是C# WinForms程序調(diào)用Python腳本的完整代碼案例的詳細(xì)內(nèi)容,更多關(guān)于C# WinForms調(diào)用Python腳本的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn)
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
C#實(shí)現(xiàn)將PPT轉(zhuǎn)換成HTML的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將PPT轉(zhuǎn)換成HTML的方法,非常實(shí)用的功能,需要的朋友可以參考下2014-08-08
WPF使用DrawingContext實(shí)現(xiàn)簡單繪圖
這篇文章主要為大家詳細(xì)介紹了WPF如何使用DrawingContext實(shí)現(xiàn)簡單繪圖,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解下2024-02-02
將文件夾下所有文件輸出到日志文件中 c#遞歸算法學(xué)習(xí)示例
這篇文章主要介紹了將文件夾下所有文件輸出到日志文件中,通過這個(gè)示例我們學(xué)習(xí)一下遞歸算法的使用方法2014-01-01
json格式數(shù)據(jù)分析工具PageElement類分享(仿Session寫法)
json格式數(shù)據(jù)分析工具PageElement類分享,可像Session一樣自由獲取Json元素的Key與Value。并可方便與ADO進(jìn)行交互2013-12-12
C#/VB.NET?將Word與Excel文檔轉(zhuǎn)化為Text
這篇文章主要介紹了C#/VB.NET?將Word與Excel文檔轉(zhuǎn)化為Text,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08

