辛苦堆砌,转载请注明出处,谢谢!
最进工作中涉及Android端和服务器端通过Soap进行通信,就不可避免的需要对接Soap服务,抽空用Python做了一个小工具,用来实现Soap服务的测试。该小工具主要使用了PyQt5和suds-py3两个模块,PyQt5是Qt的Python版图形界面库,之前本人用过Qt C++的库,所以对Qt有些基础,所以选择了PyQt5;suds-py3则是针对Python3.x的Soap客户端。使用前去要安装对应的模块,首先是PyQt5
pip install pyqt5
pip install suds-py3
import logging
logging.basicConfig(level=logging.DEBUG)
from spyne import Application, rpc, ServiceBase, Unicode
from spyne import Iterable
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
class HelloWorldService(ServiceBase):
@rpc(Unicode, _returns=Unicode)
def say_hello(ctx, name):
if name:
return 'Hello, %s' % name
else:
return 'Hello'
application = Application([HelloWorldService],
tns='http://spyne.examples.hello/',
in_protocol=Soap11(),
out_protocol=Soap11()
)
if __name__ == '__main__':
from wsgiref.simple_server import make_server
wsgi_app = WsgiApplication(application)
server = make_server('0.0.0.0', 8000, wsgi_app)
server.serve_forever()
from PyQt5.QtWidgets import QDialog, QLabel, QLineEdit, QTextEdit, QPushButton, QVBoxLayout, QHBoxLayout, QGridLayout, \
QMessageBox
from PyQt5.QtCore import Qt, pyqtSignal, QObject
from suds.client import Client
from suds import MethodNotFound
from suds.transport import TransportError
import json
from global_params import DEFAULT_WSDL
class WebServiceDialog(QDialog):
class Signals(QObject):
request_complete = pyqtSignal(str)
def __init__(self, parent=None):
super(WebServiceDialog, self).__init__(parent)
wsdl_label = QLabel('WSDL:', self)
self.wsdlLineEdit = QLineEdit(self)
self.wsdlLineEdit.setText(DEFAULT_WSDL)
method_label = QLabel('方法:', self)
self.methodLineEdit = QLineEdit(self)
param_label = QLabel('参数字典:', self)
self.paramTextEdit = QTextEdit(self)
self.paramTextEdit.setFixedHeight(200)
response_label = QLabel('响应', self)
self.responseTextEdit = QTextEdit(self)
self.responseTextEdit.setFixedHeight(200)
self.responseTextEdit.setReadOnly(True)
form_layout = QGridLayout()
form_layout.addWidget(wsdl_label, 0, 0, 1, 1)
form_layout.addWidget(self.wsdlLineEdit, 0, 1, 1, 1)
form_layout.addWidget(method_label, 1, 0, 1, 1)
form_layout.addWidget(self.methodLineEdit, 1, 1, 1, 1)
form_layout.addWidget(param_label, 2, 0, 1, 1)
form_layout.addWidget(self.paramTextEdit, 2, 1, 1, 1)
form_layout.addWidget(response_label, 3, 0, 1, 1)
form_layout.addWidget(self.responseTextEdit, 3, 1, 1, 1)
self.okButton = QPushButton('确定', self)
self.cancelButton = QPushButton('取消', self)
button_layout = QHBoxLayout()
button_layout.addStretch()
button_layout.addWidget(self.okButton)
button_layout.addWidget(self.cancelButton)
button_layout.addStretch()
main_layout = QVBoxLayout()
main_layout.addLayout(form_layout)
main_layout.addLayout(button_layout)
self.okButton.clicked.connect(self.send_request)
self.cancelButton.clicked.connect(self.reject)
self.signal = self.Signals()
self.signal.request_complete.connect(self.request_complete)
self.setLayout(main_layout)
self.setWindowTitle('Soap调用测试')
self.setWindowFlags(Qt.WindowCloseButtonHint)
self.setMinimumWidth(500)
self.setFixedHeight(550)
def request_complete(self, ret):
self.responseTextEdit.setText(ret)
def send_request(self):
try:
client = Client(self.wsdlLineEdit.text())
except ValueError:
QMessageBox.information(self, "错误", "wsdl错误", QMessageBox.No)
return
params_str = self.paramTextEdit.toPlainText()
if params_str:
try:
params = eval(params_str)
if not isinstance(params, dict):
raise NameError
except NameError:
QMessageBox.information(self, "错误", "参数格式错误,请输入字典", QMessageBox.No)
return
else:
params = {}
try:
ret = client.service.__getattr__(self.methodLineEdit.text())(**params)
self.signal.request_complete.emit(ret)
except MethodNotFound:
QMessageBox.information(self, "错误", "没有该方法", QMessageBox.No)
return
except TransportError:
QMessageBox.information(self, "错误", "请求错误", QMessageBox.No)
return
DEFAULT_WSDL = r'http://192.168.6.27:8000/?wsdl'
from PyQt5.Qt import QApplication
from web_service_dialog import WebServiceDialog
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
web_service_dialog = WebServiceDialog()
web_service_dialog.show()
sys.exit(app.exec_())
感兴趣的尝试一下,这里仅仅方便我的使用,如果大家有其他需求,可以在此基础上改进,比如可以添加namespace和上传文件等。