以前都是使用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程序,然後使用命令行方式運行,結果都一樣)打印輸出如下: