在C#中调用pyinstaller打包的exe程序以及打包rasterio库的问题

项目目标要求为在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

http://t.csdnimg.cn/U3psU

python - Something wrong with how I'm bundling rasterio into an executable - Stack Overflow

以及chatgpt3.5

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值