c#和Python交互,完美解决Python调用OpenCV等第三方库以及分发时需配置python环境的问题

news2024/11/19 17:34:32

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、问题分析
  • 二、解决方案
    • 第一个问题
    • 第二个问题
  • 三、结果及源码
  • 四、总结


前言

关于C#如何调用Python,网上提供了很多解决方案,有用ironPython的,也有把python代码打包成exe的,还有通过process类调用python的,但这些方案或多或少都有一些缺陷,比如ironPython无法调用第三方库,打包成exe运行速度太慢等。本文主要针对Process类调用python分发给别人使用时候需要安装python环境的问题提出一个解决方案。


提示:以下是本篇文章正文内容,下面案例可供参考

一、问题分析

C#如何调用Python,有一个很经典的解决方案,就是使用C#的Process类创建一个进程,这个进程实际上是为了Python解释器所开辟的,通过这个进程就可以完美调用Python代码了。这个方案的原理其实就相当于你自己使用python解释器去执行一段python代码,只不过“使用Python解释器”这个过程不是手动执行的,而是C#通过process类自动执行。关键代码见下

            Process P = new Process();
            //当前debug目录路径
            string curPath = System.Environment.CurrentDirectory;
            //需要调用的python代码文件
            string path =  curPath + "\\" + sArgName;
            //python解释器的路径
            P.StartInfo.FileName = curPath + "\\" + "python3\\python.exe";
            //传递的参数,注意,参数数组从0开始索引,第0个参数永远是python代码路径
            //从第一个参数开始是函数的形参
            string sArguments = path;

这里有两个问题:
第一个,当python代码中调用了第三方库,python解释器如何知道去哪里找到第三方库的位置。
第二,当分发给一个没有装过Python的用户使用时,怎样可以不让用户下载Python,而是可以直接使用。

二、解决方案

第一个问题

如果Python代码中引用了第三库,那么Python解释器会从它的同级目录、环境变量以及手动添加的目录中寻找相应的库。从python的安装目录我们就可以明白这一点,下图是笔者的python安装目录
在这里插入图片描述
当你调用了Python.exe时,其会在同级目录中的LIB文件夹中的site-packages文件夹搜索对应的第三方库,找到了则会成功运行,反之则报错。

第二个问题

分发给用户时,若用户没有安装python环境,则在你电脑能运行的代码,在用户那边会因为找不到相应的模块而报错。一般的解决方案是给用户安装一个python环境,但这样无疑会影响用户体验,最好的解决方案是在分发过去的工程文件中将python环境配置好。
从第一个问题中可以得到启发,python解释器会在同级目录中找寻第三方库以及其他依赖的文件,那我们可以在工程文件中新建一个python文件夹,然后再其中配置python的环境。具体操作很简单,只需要把安装python解释器的那一个文件夹的东西全都复制过去就行。当然,这样的话,文件夹可能会很大,这一般是因为site-packages中的第三方库较多。只需要在复制的时候只保留site-packages中的相关库,其他无关的全都删除就可减小空间,比如笔者的demo中需要c#调用python的opencv去显示图片,那么site-packages中需要保留opencv和numpy库就行。见下图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、结果及源码

 private void button2_Click(object sender, EventArgs e)
        {
            //打开图片文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "请选择图片文件";
            ofd.InitialDirectory = @"C:\Users\17116\Desktop";
            ofd.Filter = "图片文件|*.*";
            ofd.ShowDialog();
            url = ofd.FileName;
            string[] strArr = new string[2];//参数列表
            string sArgName = "main.py";//调用的.py文件名
            //strArr[0] = textBox1.Text;
            //strArr[1] = textBox2.Text;
            strArr[0] = url;
            RunpythonScript(sArgName, strArr);//运行python
        }

        public static void RunpythonScript(string sArgName, params string[] teps)
        {
            Process P = new Process();
            //当前debug目录路径
            string curPath = System.Environment.CurrentDirectory;
            //需要调用的python代码文件
            string path =  curPath + "\\" + sArgName;
            //python解释器的路径
            P.StartInfo.FileName = curPath + "\\" + "python3\\python.exe";
            //传递的参数,注意,参数数组从0开始索引,第0个参数永远是python代码路径
            //从第一个参数开始是函数的形参
            string sArguments = path;
            foreach (string sigter in teps)
            {
                sArguments += " " + sigter;//传递参数,两次之后为 路径 参数一 参数二
            }
            P.StartInfo.Arguments = sArguments;//启动python需要的命令语句
            P.StartInfo.UseShellExecute = false;
            P.StartInfo.RedirectStandardOutput = true;
            P.StartInfo.RedirectStandardInput = true;
            P.StartInfo.RedirectStandardError = true;
            P.StartInfo.CreateNoWindow = true;
            P.Start();
            P.BeginOutputReadLine();//在应用程序的output流上异步读取数据
            P.OutputDataReceived += new DataReceivedEventHandler(P_OutputDataReceived);//事件触发器,有新的数据就读取
            P.WaitForExit();
        }
        //用于C#和python之间字符串类型数据的传递
        static void P_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            //if (!string.IsNullOrEmpty(e.Data))//如果字符串存在
            //{
            //    MessageBox.Show(Convert.ToString(e.Data));//显示结果
            //}

        }

main.py中的python代码

import cv2
import sys

def add(a,b):
    return (float(a) + float(b))

def imgshow(path):
    img = cv2.imread(path)
    cv2.imshow("img",img)
    cv2.waitKey()

imgshow(sys.argv[1])
# print(add(sys.argv[1],sys.argv[2]))

# if __name__ == '__main__':
#     print(add(sys.argv[1],sys.argv[2]))

点击图中的选择图片按钮,c#就会调用main.py文件,并通过opencv显示图片
在这里插入图片描述
在这里插入图片描述

四、总结

本文通过process类调用python,可以使用python的第三方库,并且分发给用户的时候也不需要安装python环境。但还有一个不足之处:图片等非字符串类型的数据传输问题。这是两个不同的进程,如何把python处理好的图片数据直接加载进c#的内存中,而不是通过文件的读取方式(这样会很慢),是后续的完善方向。
最后再列举几个还没实验过的C#调用python的思路:
1.使用 Python.NET 库:Python.NET 是一个用于在 .NET 平台上运行 Python 代码的库,它提供了 C# 和 Python 之间的接口。您可以使用 Python.NET 库,在 C# 程序中调用 Python 代码。

2.使用 Pyjion:Pyjion 是一个开源的 JIT 编译器,它可以将 Python 代码编译为 .NET 的机器码。您可以使用 Pyjion,在 C# 程序中调用编译后的 Python 代码。
P.S.需要完整代码的可以在这个链接下载,博主也需要一些积分来下载资源,感兴趣的希望能多多支持一下。完整代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react组件深度解读

五、React 核心是组件 在 React 中,我们使用组件(有状态、可组合、可重用)来描述 UI 。 在任何编程语言中,你都可以将组件视为简单的函数。 React 组件也一样, 它的输入是 props,输出是关于 UI 的描述。我…

Win11 WSL Linux子系统安装与注销 配置conda环境 启动jupyter

1 前言 本篇博客讲解如何在Windows11系统中安装与注销Linux子系统,并配置conda环境、jupyter环境,实现在Local浏览器启动jupyter并运行项目。 2 安装Linux子系统(参考文章[1]) 1.1 WSL 在任务栏中的搜索功能中,搜索…

合并多文件后分组再结构化

【问题】 Heres the problem statement: In a folder in HDFS, therere a few csv files with each row being a record with the schema (ID, attribute1, attribute2, attribute3). Some of the columns (except ID) could be null or empty strings, and no 2 records wi…

汇编语言常用DOS功能调用示例

1.利用DOS功能调用输出响铃(响铃的ASCII码为07H)。建立源程序文件HELLO.ASM,通过汇编程序得到目标文件RING.OBJ以及列表文件RING.LST,通过连接程序得到可执行文件性文件 RING.EXE。对可执行性文件进行调试。 (1&…

【数据结构】——栈和队列

目录 1.栈 1.1栈的概念及结构 1.2栈的实现 1.2.1具体实现 Stack.h 栈初始化 栈销毁 入栈 出栈 取栈顶数据 判空 栈中有效元素的个数 全部Stack.c的代码 测试Test.c代码 2.队列 2.1队列的概念及结构 2.2队列的实现 Queue.h 队列初始化 队列销毁 队尾入队列…

Tomcat8.0使用tomcat-redis-session-manager共享session【开源】,tomcat实现session共享

前言 【可跳过,比较简单】 由于以前的项目配置了多个tomcat服务使用了nginx代理,但是关闭某个tomcat的时候登录用户信息丢失,用户得重新登录,这就让人体验不好了;我们可以复制各个tomcat服务的session来实现的sessio…

【供给需求优化算法】基于适应度-距离-平衡供给需求优化算法FDB-SDO附matlab代码

​✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法…

毕设选题推荐基于python的django框架的学生课程管理系统

💖🔥作者主页:计算机毕设老哥🔥 💖 精彩专栏推荐订阅:在 下方专栏👇🏻👇🏻👇🏻👇🏻 Java实战项目专栏 Python实…

前端二面常见手写面试题(必备)

用正则写一个根据name获取cookie中的值的方法 function getCookie(name) {var match document.cookie.match(new RegExp((^| ) name ([^;]*)));if (match) return unescape(match[2]); }获取页面上的cookie可以使用 document.cookie 这里获取到的是类似于这样的字符串&…

新一代推理部署工具FastDeploy与十大硬件公司联合打造:产业级AI模型部署实战课...

人工智能产业应用发展的越来越快,开发者需要面对的适配部署工作也越来越复杂。层出不穷的算法模型、各种架构的AI硬件、不同场景的部署需求、不同操作系统和开发语言,为AI开发者项目落地带来极大的挑战。为了解决AI部署落地难题,我们发布了新…

(附源码)springboot校园跳蚤市场 毕业设计 646515

基于Springboot校园跳蚤市场 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。现代社会越来…

Python解题 - CSDN周赛第14期 - 单词编码

本期其实没啥好写的,都是数学题,和算法关系不大,唯手熟尔。而且又出现了同一天的每日一练中包含了赛题,这算不算官方泄题呢?看来下次在竞赛之前先做完每日一练大有益处呢。 第一题:字符串全排列 对K个不同字…

算法leetcode|21. 合并两个有序链表(rust重拳出击)

文章目录21. 合并两个有序链表:样例 1:样例 2:样例 3:提示:原题传送门:分析:题解:rustgoccpythonjava21. 合并两个有序链表: 将两个升序链表合并为一个新的 升序 链表并…

一款基于SpringBoot+layui 开源的固定设备资产管理系统源码 源码免费分享

淘源码:国内专业的免费源码下载平台 分享一款开源的固定设备资产管理系统源码,系统可对常用资产设备进行信息化管理,包含自定义支持各类设备、自带导入导出、维护工作统计、采购管理、文档管理、合同管理等功能,包含对资产的登记、…

如何优雅的设计和使用缓存?

背景 在之前的文章中你应该知道的缓存进化史介绍了爱奇艺的缓存架构和缓存的进化历史。俗话说得好,工欲善其事,必先利其器,有了好的工具肯定得知道如何用好这些工具,本篇将介绍如何利用好缓存。 1.确认是否需要缓存 在使用缓存…

CentOS7 修改ip、MAC、UUID

对于复制的虚拟机,在开机时,VMware自动为其分配了相同的Mac地址以及IP地址(除IP地址是dhcp自动获取外) UUID(Universally Unique Identifier)是系统层面的全局唯一标识符号,Mac地址以及IP地址是网络层面的标识号 两台不…

dtb如何转换到platform_device

分2步,第一步是首先转换为device_node,第二步device_node转换为platform_device。 第一步 /*** unflatten_device_tree - create tree of device_nodes from flat blob** unflattens the device-tree passed by the firmware, creating the* tree of st…

mysql常用索引

1.普通索引 navicat中为NORMAL 语句为 ADD INDEX //采用普通索引的方式可以大大提高数据库的工作效率 2.唯一索引 navicat中为NORMAL 语句为 ADD UNIQUE INDEX //采用唯一索引的方式可以大大提高数据库的工作效率、并且数据无重复 3.主键索引 navicat中为主键 语句为 AD…

ALSA系统简析

一 音频架构 如图所示 是 嵌入式系统的音频连接 音频编解码器将数字音频信号 转换成 扬声器播放所需要的模拟声音信号。而通过麦克风时,则执行相反的过程。 数字音频信号通过 PCM技术对模拟信号以某个比特率采样得到的,编解码器的任务就是以支持的PCM…

非零基础自学计算机操作系统 第1章 操作系统概述 1.4 操作系统的分类 1.4.1 多道批处理操作系统 1.4.2 分时操作系统

非零基础自学计算机操作系统 文章目录非零基础自学计算机操作系统第1章 操作系统概述1.4 操作系统的分类1.4.1 多道批处理操作系统1.4.2 分时操作系统第1章 操作系统概述 1.4 操作系统的分类 按照操作系统的功能可将其分为以下几类:多道批处理操作系统、分时操作系…