Есть ли какой-нибудь пример кода cpython (не IronPython), который может вызывать службу Windows Communication Foundation (WCF)?
WCF и Python
Ответ 1
WCF должен раскрывать функциональность через протокол связи. Я думаю, что наиболее часто используемый протокол, вероятно, SOAP через HTTP. Предположим, что что вы используете тогда.
Посмотрите эту главу в Dive Into Python. Он покажет вам, как сделать SOAP-вызовы.
Я не знаю единого способа вызова службы WCF в Python, независимо от того, Протокол.
Ответ 2
Я использовал suds.
from suds.client import Client
print "Connecting to Service..."
wsdl = "http://serviceurl.com/service.svc?WSDL"
client = Client(wsdl)
result = client.service.Method(variable1, variable2)
print result
Это должно заставить вас начать. Я могу подключиться к открытым службам из WCF и слоя RESTful. Для обеспечения того, что вам нужно, нужно провести некоторое массирование данных, особенно если вам нужно привязать к нескольким пространствам имен.
Ответ 3
TL; DR: для wsHttpBinding (SOAP 1.2) используйте zeep
В случае, если у кого-то возникают проблемы с использованием suds (или suds-jurko) с WCF и wsHttpBinding (то есть SOAP 1.2):
- suds в значительной степени мертв (даже pip не может установить его на python 3)
- Судж-Юрко кажется мертвым. Релиз 0.6 имеет очень досадную бесконечную ошибку рекурсии (по крайней мере, для WSDL, предоставляемой нашим сервисом), которая исправлена в подсказке, но не выпущена, и с момента ее написания в феврале 17 года прошло 1,5 года (на момент написания этой статьи). совершить.
Он работает на Python 3, но не поддерживает SOAP 1.2. Ответ Советникова - попытка заставить его работать с 1.2, но мне не удалось заставить его работать на меня. - Zeep, кажется, является текущим способом пойти и работать из коробки (я не связан с Zeep, это просто работает для меня, и я провел несколько часов, стуча головой о кирпичную стену, пытаясь заставить работать пену).
Чтобы Zeep работал, конфигурация хоста службы WCF должна включать <security mode = "None"/> в узлеwsHttpBinding. На самом деле, Zeep поддерживает WS-SE на основе имени и подписи (x509), но я не пробовал, так что могу ' не говорить о каких-либо проблемах вокруг.
Ответ 4
Просто, чтобы помочь кому-то получить доступ к службе WCF SOAP 1.2 с помощью WS-Addressing с использованием пены. Основная проблема заключается в том, чтобы вводить имя действия в каждое сообщение.
Этот пример для порта python 3 и suds https://bitbucket.org/jurko/suds.
В примере используется пользовательская аутентификация на основе HTTP-заголовков, я оставляю ее как есть.
TODO: Автоматически получать api_direct_url из WSDL (теперь он жестко закодирован).
from suds.plugin import MessagePlugin
from suds.sax.text import Text
from suds.wsse import Security, UsernameToken
from suds.sax.element import Element
from suds.sax.attribute import Attribute
from suds.xsd.sxbasic import Import
api_username = 'some'
api_password = 'none'
class api(object):
api_direct_url = 'some/mex'
api_url = 'some.svc?singleWsdl|Wsdl'
NS_WSA = ('wsa', 'http://www.w3.org/2005/08/addressing')
_client_instance = None
@property
def client(self):
if self._client_instance:
return self._client_instance
from suds.bindings import binding
binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope')
api_inst = self
class _WSAPlugin(MessagePlugin):
def marshalled(self, context):
api_inst._marshalled_message(context)
self._client_instance = Client(self.api_url,
plugins=[_WSAPlugin()],
headers={'Content-Type': 'application/soap+xml',
'login':api_username,
'password': api_password}
)
headers = []
headers.append(Element('To', ns=self.NS_WSA).setText(self.api_direct_url))
headers.append(Element('Action', ns=self.NS_WSA).setText('Blank'))
self._client_instance.set_options(soapheaders=headers)
cache = self._client_instance.options.cache
cache.setduration(days=10)
return self._client_instance
def _marshalled_message(self, context):
def _children(r):
if hasattr(r, 'children'):
for c in r.children:
yield from _children(c)
yield c
for el in _children(context.envelope):
if el.name == 'Action':
el.text = Text(self._current_action)
return
_current_action = None
def _invoke(self, method, *args):
try:
self._current_action = method.method.soap.action.strip('"')
return method(*args)
finally:
self._current_action = None
def GetRequestTypes(self):
return self._invoke(self.client.service.GetRequestTypes)[0]
def GetTemplateByRequestType(self, request_type_id):
js = self._invoke(self.client.service.GetTemplateByRequestType, request_type_id)
return json.loads(js)
def GetRequestStatus(self, request_guid):
return self._invoke(self.client.service.GetRequestStatus, request_guid)
def SendRequest(self, request_type_id, request_json):
r = json.dumps(request_json, ensure_ascii=False)
return self._invoke(self.client.service.SendRequest, request_type_id, r)
Ответ 5
Я не знаю никаких прямых примеров, но если служба WCF включена REST, вы можете получить доступ к ней через POX (обычный старый XML) с помощью методов REST/etc (если у службы есть какие-либо). Если вы контролируете службу, вы можете также вывести конечные точки через REST.
Ответ 6
если вам нужна двоичная сериализованная связь по tcp, тогда рассмотрите реализацию решения, например, Thrift.
Ответ 7
Даже если нет конкретного примера вызова WCF из Python, вы должны иметь возможность полностью использовать SOAP-совместимый сервис с WCF. Затем все, что вам нужно сделать, это найти несколько примеров того, как вызвать обычную SOAP-службу с Python.
Простейшим будет использование BasicHttpBinding в WCF, а затем вы можете поддерживать свои собственные сеансы, передавая токен сеанса с каждым запросом и ответом.