web-dev-qa-db-ja.com

WCFとPython

Windows Communication Foundation(WCF)サービスを呼び出すことができる cpython (IronPythonではない)クライアントのサンプルコードはありますか?

24
bhadra

WCFは、通信プロトコルを介して機能を公開する必要があります。最も一般的に使用されるプロトコルはおそらくSOAP overHTTPです。それがそのとき使用しているものであると仮定しましょう。

Dive Into Pythonのこの章 を見てください。 SOAP呼び出しを行う方法を示します。

通信プロトコルに関係なく、PythonでWCFサービスを呼び出す統一された方法を知りません。

8
Dan

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レイヤーから公開されたサービスに接続できます。特に複数の名前空間にバインドする必要がある場合は、必要なことを実行するためにデータのマッサージが必要です。

19
r3nrut

TL; DR:wsHttpBinding(SOAP 1.2)の場合は zeep を使用します


誰かがWCFとwsHttpBinding(SOAP 1.2))でsuds(またはsuds-jurko)を使用するのに問題がある場合:

  • sudsはほとんど死んでいます(python 3)にpipインストールすることさえできません)
  • suds-jurkoは一種の死んだようです。 0.6リリースには、非常に厄介な無限再帰バグがあり(少なくとも私たちのサービスによって公開されたWSDLで)、ヒントで修正されていますが、リリースされておらず、最後から1。5年(この記事の執筆時点では2017年2月)です。コミット。
    これはpython 3で動作しますが、SOAP 1.2をサポートしていません。 Sovetnikovの答え はそれは1.2で動作しますが、私はそれを私のために動作させることができませんでした。
  • zeepは、箱から出してすぐに使える現在の方法のようです(zeepとは提携していません。それは私にとってはうまくいき、泡を機能させるためにレンガの壁に頭をぶつけて数時間過ごしました)。 Zeepが機能するには、WCFサービスのホスト構成でwsHttpBindingノードの下に<security mode = "None" />が含まれている必要があります。 実際、zeepは ユーザー名と署名(x509)ベースのWS-SE をサポートしているようですが、私はそれを試したことがないので、その周りの問題について話すことはできません。
3
ChrisWue

誰かがWCF SOAP 1.2 Service with WS-Addressing with suds。主な問題は、すべてのメッセージにアクション名を挿入することです。

python 3 and suds port https://bitbucket.org/jurko/suds のこの例。

例では、HTTPヘッダーに基づくカスタム認証を使用していますが、そのままにしておきます。

TODO:WSDLからapi_direct_urlを自動的に取得します(現在はハードコーディングされています)。

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)
2
Sovetnikov

直接的な例はわかりませんが、WCFサービスがREST有効になっている場合は、RESTメソッドを介してPOX(プレーンオールドXML)からアクセスできます。/etc(サービスに存在する場合)。サービスを制御している場合は、REST)を介してエンドポイントを公開することもできます。

1
Donn Felker

tCPを介したバイナリシリアル化通信が必要な場合は、Thriftのようなソリューションの実装を検討してください。

1
mamu

PythonからWCFを呼び出す特定の例がない場合でも、WCFを使用して完全にSOAP準拠のサービスを作成できるはずです。次に、実行する方法の例をいくつか見つけるだけです。 Pythonから通常のSOAPサービスを呼び出します。

最も簡単なことは、WCFでBasicHttpBindingを使用することです。その後、各要求と応答でセッショントークンを渡すことにより、独自のセッションをサポートできます。

0
Wayne Bloss