环境:
win10,Python 3.9.13
参考:
Python3简单使用xmlrpc实现RPC - 简书
https://www.jianshu.com/p/9987913cf734
目录
问题描述
之前写过:
c#远程调用linux服务器的Python脚本_c#远程登录其他服务器执行脚本-CSDN博客
https://blog.csdn.net/pxy7896/article/details/121473815
pythonnet-C#调用python脚本-含matplotlib+biopython_c# pythonnet 调用python脚本-CSDN博客
https://blog.csdn.net/pxy7896/article/details/141608138
目前遇到的问题是:
- 同事那边是windows系统、.net项目,她需要调用我这边linux服务器上的一个python脚本
- 该脚本涉及比较多的数据和程序,不方便挪动;同时,该脚本接收一个txt文件作为输入,处理后产生一个zip文件作为输出
- 使用远程调用的话,需要考虑文件的上传和下载功能
解决
思路
在linux和windows上分别实现server和client,.net项目里使用pythonnet调用client里的函数。
server
python
# _*_ coding:utf-8 _*_
from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
import xmlrpc.client
import base64
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
pass
def file_output(name):
'''
下载文件
name: 唯一标识符
'''
file_name = os.getcwd() + "/" + name
if not os.path.isfile(file_name):
return f"Error: File '{name}' does not exist."
with open(file_name, 'rb') as file:
return file.read()
def file_input(filename, filedata):
'''
上传文件
file_name: 唯一标识符
file_data: byte数据
'''
with open(filename, 'wb') as file:
file.write(base64.b64decode(filedata))
# do something ...
return f"File {filename} saved successfully."
if __name__ == '__main__':
server = ThreadXMLRPCServer(('IP', 端口), allow_none=True) # 初始化
server.register_function(file_input, 'file_input')
server.register_function(file_output, 'file_output')
print("Listening for Client")
server.serve_forever() # 保持等待调用状态
如果只需要传数据,不需要传文件名,也可以这样写:
python
# 供客户端上传文件
def file_input(data):
handle = open("xxx.txt", 'wb')
handle.write(data.data)
handle.close()
client
python
# _*_ coding:utf-8 _*_
from xmlrpc.client import ServerProxy
import xmlrpc.client
import base64
import os
server_url = "http://IP:端口"
def send_file(file_path):
with open(file_path, 'rb') as file:
filedata = file.read()
file_name = os.path.basename(file_path)
# 编码文件数据
filedata_b64 = base64.b64encode(filedata).decode('utf-8')
# 连接到服务器
with ServerProxy(server_url) as proxy:
response = proxy.file_input(file_name, filedata_b64)
print(response)
def get_file(name):
save_path = os.path.join(os.getcwd(), name + ".zip")
with ServerProxy(server_url) as proxy:
file_content = proxy.file_output(name)
if not isinstance(file_content, str):
with open(save_path, 'wb') as file:
file.write(file_content.data)
print("ok")
else:
print(file_content) # 如果返回的是错误消息
if __name__ == '__main__':
# 上传文件
file_path = "文件路径"
send_file(file_path)
# 下载文件
zip_prefix = "test"
get_file(zip_prefix)
如果是第二种file_input写法,那么对应的上传这样写:
python
server = ServerProxy("http://IP:端口", allow_none=True)
put_handle = open("路径", 'rb')
server.file_input(xmlrpc.client.Binary(put_handle.read()))
put_handle.close()
注意:client端写文件时需要使用file.write(file_content.data)
,因为file_content
不是byte
。可以用type()
打印一下,结果是:
shell
<class 'xmlrpc.client.Binary'>
debug
对方服务器积极拒绝
检查:
-
能否ping通
不过不通的话应该报错:shellTimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
-
服务器端口是否开放
-
服务器程序是否正常运行
-
server这句是不是写成localhost。应该写对外的IP
pythonserver = ThreadXMLRPCServer(('IP', 端口), allow_none=True) # 初始化
最后再检查防火墙。不过一般前几个搞定就好了。