2008-11-09 34 views
22

¿Hay algún código de ejemplo de un cliente cpython (no IronPython) que pueda llamar al servicio Windows Communication Foundation (WCF)?WCF y Python

+0

¿Podemos suponer con seguridad que está intentando llamar a un servicio basado en SOAP o REST a través de HTTP? Dudo que haya algún tipo de puente COM entre Python y un cliente WCF capaz de llamar con éxito a un servicio TCP WCF. – technomalogical

Respuesta

8

WCF necesita exponer la funcionalidad a través de un protocolo de comunicación. Creo que el protocolo más utilizado es probablemente SOAP sobre HTTP. Supongamos que es lo que está usando entonces.

Eche un vistazo a this chapter in Dive Into Python. Le mostrará cómo hacer llamadas SOAP.

No conozco una forma unificada de llamar a un servicio WCF en Python, independientemente del protocolo de comunicación .

+2

Solo obtuve basicHttpBinding para trabajar. Si alguien sabe cómo hacer que wsHttpBinding funcione, publíquelo aquí también. –

0

Incluso si no hay un ejemplo específico de llamar a WCF desde Python, debería poder hacer un servicio completamente compatible con SOAP con WCF. Entonces, todo lo que tiene que hacer es encontrar algunos ejemplos de cómo llamar a un servicio SOAP normal desde Python.

Lo más simple será usar BasicHttpBinding en WCF y luego puede soportar sus propias sesiones pasando un token de sesión con cada solicitud y respuesta.

1

No conozco ningún ejemplo directo, pero si el servicio WCF está habilitado para REST, puede acceder a él a través de POX (XML simple llano) a través de los métodos REST/etc (si el servicio tiene alguno). Si tiene el control del servicio, también podría exponer los puntos finales a través de REST.

1

si necesita comunicación serializada binaria sobre tcp, entonces considere implementar una solución como Thrift.

17

He usado .

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 

Eso debería comenzar. Puedo conectarme a servicios expuestos de WCF y una capa RESTful. Es necesario que haya algún masaje de datos para ayudarlo a hacer lo que necesita, especialmente si necesita vincular varios espacios de nombres.

+1

Ningún módulo llamado suds.client, ¿de dónde obtienes espuma? –

+0

@ItalyLevin necesitas usar pip. – stephen

+0

Recibí el error No module named 'client' cuando intento instalar con pip en Windows 7 – user2258651

2

Solo para ayudar a alguien a acceder al servicio WCF SOAP 1.2 con WS-Addressing utilizando espuma. El principal problema es inyectar nombre de acción en cada mensaje.

Este ejemplo para python 3 y el puerto de espuma https://bitbucket.org/jurko/suds.

Ejemplo utiliza autenticación personalizada basada en encabezados HTTP, la dejo tal como está.

TODO: Obtiene automáticamente api_direct_url de WSDL (en este momento está codificado).

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) 
0

TL; DR: Para wsHttpBinding (SOAP 1.2) utilizar zeep


En caso de que alguien está teniendo problemas para el uso de la espuma (o espuma-Jurko para esa materia) con WCF y wsHttpBinding (que es SOAP 1.2):

  • espuma es prácticamente muerto (ni siquiera puede pip instalarlo en Python 3)
  • espuma-jurko parece un poco de muertos. La versión 0.6 tiene un error de recursión infinito muy molesto (al menos en el WSDL expuesto por nuestro servicio) que se soluciona en la sugerencia pero que no se ha lanzado y ha sido 1.5 años (al momento de escribir esto en Feb'17) desde el último compromiso.
    Funciona en python 3 pero no es compatible con SOAP 1.2. Sovetnikov's answer es un intento de que funcione con 1.2, pero no he logrado que funcione para mí.
  • zeep parece ser el camino actual y funcionó de la caja (no estoy afiliado con Zeep, simplemente funciona para mí y pasé varias horas golpeando mi cabeza contra una pared de ladrillo tratando de hacer espuma) . Para que Zeep funcione, la configuración del host del servicio WCF debe incluir el modo de seguridad < = "None"/> en el nodo wsHttpBinding.
+0

puede agregar un ejemplo de cómo implementar wsHttpBinding, atascado durante horas no puede implementarlo. – harshil9968

+0

@ harshil9968: No estoy 100% seguro de lo que está buscando. La creación de una instancia de un cliente Zeep es tan simple como 'client = zeep.Client ('http: // computerip: port/myservice /? wsdl ') '. Cómo crear una implementación del servicio WCF está un poco fuera del alcance de esta pregunta – ChrisWue

+0

que esto crea con http-binding, no wshttp-binding. Recibo un error del cliente debido a eso. – harshil9968