项目目标要求为在C#做一个界面,直接调用写好的python代码,然而理想很丰满,现实很残酷,中间遇到了种种困难。最主要的难题在rasterio的的打包
1、写一个C#界面
加入listBox button textBox控件
由于本次需要输入不确定数目的参数所以使用了listBox,用‘,’分割,在python代码中将其打包为元组
.
2、打包写好的python代码(此处的代码需要改成接收参数的代码)
2.1 python代码例子
在python中接收参数
import joblib
import rasterio
import numpy as np
import numpy.ma as ma
import sys
def plus(args,l,s,t):
a = '?'.join(args)
c = '--a--' + a + '--l--' + l + '--s--' + s + '--t--' + str(t)
d = remove(5, 4)
e = str(d) + '--r--' + str(c)
return e
def remove(a,b):
return a - b
if __name__ == '__main__':
# Ensure that there are at least two command-line arguments
# if len(sys.argv) < 3:
# sys.exit(1)
# Get command-line arguments
# arg1 = sys.argv[1]
# arg2 = sys.argv[2]
# 从 C# 中传递的多个参数
arguments_from_csharp = sys.argv[1:]
combined_arguments = arguments_from_csharp[0]
# 将字符串分割为元组
args_tuple = tuple(combined_arguments.split(','))
listPathsString = args_tuple
labelPathString = arguments_from_csharp[1]
storePathString = arguments_from_csharp[2]
treeNumString = arguments_from_csharp[3]
treeNum = int(treeNumString)
# 调用 read_tf_bands 方法
# read_tf_bands(arguments_from_csharp)
result = plus(listPathsString, labelPathString, storePathString, treeNum)
print(result)
sys.stdout.flush()
2.2 pyinstaller
使用pyinstaller来打包,关于pyinstaller我参考了这篇帖子:http://t.csdnimg.cn/hUUsz打包好的文件可以看到路径
但是注意看我的python代码中import了rasterio这是一个关于遥感图像处理的库,虽然我这里没有调用这个但是我的项目需要这个库,所以在这里需要打包这个库到项目中,按理说他应该顺利打包进去的,但是他没有,在cmd中运行后报错modulenotfounderror no module named ‘rasterio.xxx‘、‘rasterio.xxx'说明并没有将其打包进去
在经过查阅资料,http://t.csdnimg.cn/TSdTh
python - Something wrong with how I'm bundling rasterio into an executable - Stack Overflow
询问chatgpt后,我使用pyinstaller打包.spec文件,成功将其打包进去,打包后的exe文件有200MB
spec文件为pyinstaller其打包的附属文件
打包命令:
(虚拟环境) C:\Users\xxx> pyinstaller -F C:\xxx.spec
['E:\\xxxx\\xxxxx.py']为你的py文件
name='xxxxxyourname',为生成的exe文件
# -*- mode: python ; coding: utf-8 -*-
import pkgutil
import rasterio
# list all rasterio and fiona submodules, to include them in the package
additional_packages = list()
for package in pkgutil.iter_modules(rasterio.__path__, prefix="rasterio."):
additional_packages.append(package.name)
block_cipher = None
a = Analysis(['E:\\xxxx\\xxxxx.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=additional_packages,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='xxxxxyourname',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None )
2.3 检查一下exe
打包好的exe可以在cmd中运行一下,比较简单的方法为找到文件存在的文件夹,在文件路径中输入cmd调出命令行
然后直接调用其xx.exe文件
C:\xxx\xxx.exe argu1 argu2 argu3 argu4
看到正确输出后就ok了
3、调用python的代码
在C#中调用python的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
private List<string> selectedFiles = new List<string>();
public Form2()
{
InitializeComponent();
// 禁用窗体的最大化按钮
this.MaximizeBox = false;
}
//点击确定后调用python程序
private void PassListBoxItemsToPython()
{
// 构建包含所有路径的字符串,使用逗号或其他分隔符分隔路径
string listPathsString = string.Join(",", fileListBox.Items.Cast<string>());
Console.WriteLine(listPathsString);
string labelPathString = labelText.Text;
string storePathString = divText.Text;
string arguments = listPathsString + " " + labelPathString + " " + storePathString;
// 创建并显示等待窗口
WaitingForm waitingForm = new WaitingForm();
waitingForm.Show();
// 启动 Python 应用程序进程,并传递路径字符串作为参数
StartPythonAppProcess(arguments);
// 关闭等待窗口
waitingForm.Close();
}
private void StartPythonAppProcess(string paths)
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = @"E:\rice_classifier\1.exe", // Python 应用程序路径
Arguments = paths, // 传递路径字符串作为参数
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
//using 语句确保在其作用域结束时,Process 对象会被正确释放,包括关闭相关的资源。
//不需要显式调用 Close() 方法。资源管理会由 using 语句自动完成。
using (Process process = new Process { StartInfo = startInfo })
{
process.Start();
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
process.WaitForExit();
}
}
private void okbutton_Click(object sender, EventArgs e)
{
PassListBoxItemsToPython();
}
// 自定义等待窗口
public class WaitingForm : Form
{
private ProgressBar progressBar;
private Timer animationTimer;
private int animationCounter;
public WaitingForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
// 在这里设置等待窗口的外观和布局
this.Text = "等待中...";
this.Size = new System.Drawing.Size(200, 100);
this.StartPosition = FormStartPosition.CenterScreen;
this.ControlBox = false;
this.ShowInTaskbar = false;
this.TopMost = true;
}
}
//添加多个数据到listBox
private void addButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "选择文件";
openFileDialog.Filter = "所有文件 (*.*)|*.*";
openFileDialog.Multiselect = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// 将选择的文件路径添加到 ListBox
fileListBox.Items.AddRange(openFileDialog.FileNames);
// 可选:将 ListBox 滚动到最后一个添加的项目
fileListBox.TopIndex = fileListBox.Items.Count - 1;
// 将选择的文件路径添加到列表
selectedFiles.Add(openFileDialog.FileName);
}
}
private void fileListBox_SelectedIndexChanged(object sender, EventArgs e)
{
fileListBox.HorizontalScrollbar = true;
fileListBox.ScrollAlwaysVisible = true;
}
private void removeButton_Click(object sender, EventArgs e)
{
// 获取选定的项
ListBox.SelectedObjectCollection selectedItems = fileListBox.SelectedItems;
// 逐个从 ListBox 中移除选定的项
foreach (var selectedItem in selectedItems.Cast<string>().ToList())
{
fileListBox.Items.Remove(selectedItem);
}
}
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("11111");
}
//获取一个文件夹路径
private void button2_Click(object sender, EventArgs e)
{
using (var folderBrowserDialog = new FolderBrowserDialog())
{
DialogResult result = folderBrowserDialog.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowserDialog.SelectedPath))
{
// 将选择的文件夹路径显示在 TextBox 中
divText.Text = folderBrowserDialog.SelectedPath;
}
}
}
private void labelButton_Click(object sender, EventArgs e)
{
OpenFileData_.openFileData(labelText);
}
}
public class OpenFileData_
{
public static void openFileData(TextBox textBox)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
// 设置对话框的标题
openFileDialog.Title = "选择文件";
// 设置对话框的初始目录
openFileDialog.InitialDirectory = "C:\\";
// 设置文件类型过滤
openFileDialog.Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*";
// 如果用户点击了 "确定" 按钮
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// 获取用户选择的文件路径
string selectedFilePath = openFileDialog.FileName;
textBox.Text = selectedFilePath;
// 在控制台输出文件路径
Console.WriteLine("用户选择的文件路径: " + selectedFilePath);
}
}
}
}
参考帖子:
http://t.csdnimg.cn/hUUsz
http://t.csdnimg.cn/TSdTh
python - Something wrong with how I'm bundling rasterio into an executable - Stack Overflow
以及chatgpt3.5