以前都是使用C#调用webservice服务或者wcf服务,由于特殊需求,需要调用python进行处理,大概流程是:客户端使用C#,服务端使用python,客户端发起调用,服务器执行,服务端执行后把结果返回给客户端
通信的桥梁可以使用XMLRPC
2019年12月9日修改:
注意:如果把python代码运行在远程的服务器上,需要把下面的服务端的python代码中的代码server = SimpleXMLRPCServer(('localhost',666))改为
server = SimpleXMLRPCServer(("",666), allow_none=True),不然会出现客户端无法连接服务器的情况
本人测试使用的vs版本是vs2012
准备工作:
1 C#开发的工具
2 安装python
3 需要下载CookComputing.XmlRpcV2.dll库
不过我发现官网(fanqiang了也不行,敏感字眼居然审核不给通过)和Nuget(可能是我vs的问题)都无法下载,不过我还是把地址贴出来
Nuget地址:https://www.nuget.org/packages/xmlrpcnet
网盘地址:链接:https://pan.baidu.com/s/1wj05WR8-RNsW4qjAoHfWfA 提取码:08nw
服务端的python代码(参考别人写的)如下:
from xmlrpc.server import SimpleXMLRPCServer
def getHelloWorld():
return 'Hello world'
if __name__ == '__main__' :
server = SimpleXMLRPCServer(('localhost',666))
server.register_function(getHelloWorld, "getHelloWorld")
server.serve_forever()
客户端C#代码如下(注意要添加CookComputing.XmlRpcV2.dll的引用):
using CookComputing.XmlRpc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpCallPython
{
class Program
{
static void Main(string[] args)
{
ProxyInterface proxy = (ProxyInterface)XmlRpcProxyGen.Create(typeof(ProxyInterface));
Console.WriteLine(proxy.getHelloWorld());
Console.ReadLine();
}
}
}
[XmlRpcUrl("http://localhost:666")]
public interface ProxyInterface : IXmlRpcProxy
{
[XmlRpcMethod("getHelloWorld")]
string getHelloWorld();
}
使用cmd运行python服务端,如下图:
运行客户端,结果如下图:
更新于2019年12月9日
例子2:客户端发送图片到服务器,服务器保存图片
服务端的pthon代码如下:
import base64
from xmlrpc.server import SimpleXMLRPCServer
def zi_tu(b_tu):
tu_b = base64.b64decode(b_tu)
with open('C:\\Users\\Administrator\\Desktop\\tu.png', 'wb') as fp:
fp.write(tu_b)
def getHelloWorld(b_tu):
zi_tu(b_tu)
return 'Hello world'
if __name__ == '__main__' :
server = SimpleXMLRPCServer(("",666), allow_none=True)
server.register_function(getHelloWorld, "getHelloWorld")
server.serve_forever()
客户端C#代码如下(注意要添加CookComputing.XmlRpcV2.dll的引用和在工程目录的bin/Debug的目录下放一张名为test.png的图片,同时还需要修改ip地址为你的ip地址):
using CookComputing.XmlRpc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpCallPython
{
class Program
{
static void Main(string[] args)
{
ProxyInterface proxy = (ProxyInterface)XmlRpcProxyGen.Create(typeof(ProxyInterface));
//Console.WriteLine(proxy.getHelloWorld());
FileStream fs = File.OpenRead("test.png"); //OpenRead
int filelength = 0;
filelength = (int)fs.Length; //获得文件长度
Byte[] image = new Byte[filelength]; //建立一个字节数组
fs.Read(image, 0, filelength); //按字节流读取
string ImageString=Convert.ToBase64String(image);
try
{
Console.WriteLine(proxy.getHelloWorld(ImageString));
}
catch (Exception ex)
{
Console.WriteLine("发生异常");
}
Console.ReadLine();
}
}
}
[XmlRpcUrl("http://47.94.102.147:666")]
public interface ProxyInterface : IXmlRpcProxy
{
[XmlRpcMethod("getHelloWorld")]
string getHelloWorld(string imageString);
}
更新于2019年12月17日
例子3 C#客户端发送图片,python服务端转成可以使用opencv-python操作的对象
C#客户端的程序同例子2
python服务器程序编写如下:
注意:操作前python服务器需要安装python对应版本的opencv-python库
import base64
from xmlrpc.server import SimpleXMLRPCServer
import cv2
import numpy as np
def zi_tu(b_tu):
tu_b = base64.b64decode(b_tu)
#字节数组转换成numpy可以处理的数组
imga = np.frombuffer(tu_b, np.uint8)
#解码数组,获取opencv-python可以处理的图片对象
img = cv2.imdecode(imga,cv2.IMREAD_COLOR)
#显示图片
cv2.imshow("Image",img)
#等待,不然程序一下就过去了,显示的图片你会看不到
cv2.waitKey(0)
#打印输出,看一下图片对象的值
print(img)
def getHelloWorld(b_tu):
zi_tu(b_tu)
return 'Hello world'
if __name__ == '__main__' :
server = SimpleXMLRPCServer(("",666), allow_none=True)
server.register_function(getHelloWorld, "getHelloWorld")
server.serve_forever()
效果如下:
1 python服务器图片对话框如果不关闭,效果如下图:
2 python服务器图片对话框关闭后,效果如下图:
并且可以看到jupyter notebook(我使用jupyter notebook编写的python程序,当然你也可以使用记事本编写python程序,然后使用命令行方式运行,结果都一样)打印输出如下: