12

ネットワークデバイスとの通信に使用されるTwistedに基づくプロジェクトがあり、APIがSOAPである新しいベンダー( Citrix NetScaler )のサポートを追加しています。残念ながら、TwistedでのSOAPのサポートはまだに依存していますがSOAPpy、これはひどく時代遅れです。実際、この質問(私はチェックしたばかりです)の時点では、twisted.web.soap それ自体は21か月も更新されていません!

Twistedの優れた非同期トランスポート機能をSUDSで利用することについて、誰かが喜んで共有してくれる経験があるかどうかを尋ねたいと思います。カスタムのツイストトランスポートを接続すると、SUDSに自然にフィットするようClient.options.transportです。頭を包むのに苦労しています。

を利用して、SUDSでSOAPメソッドを非同期的に呼び出す方法を思いついたのですtwisted.internet.threads.deferToThread()が、これは私にとってはハックのように感じます。

これが私がやったことの例です、あなたにアイデアを与えるために:

# netscaler is a module I wrote using suds to interface with NetScaler SOAP
# Source: http://bitbucket.org/jathanism/netscaler-api/src
import netscaler
import os
import sys
from twisted.internet import reactor, defer, threads

# netscaler.API is the class that sets up the suds.client.Client object
host = 'netscaler.local'
username = password = 'nsroot'
wsdl_url = 'file://' + os.path.join(os.getcwd(), 'NSUserAdmin.wsdl')
api = netscaler.API(host, username=username, password=password, wsdl_url=wsdl_url)

results = []
errors = []

def handleResult(result):
    print '\tgot result: %s' % (result,)
    results.append(result)

def handleError(err):
    sys.stderr.write('\tgot failure: %s' % (err,))
    errors.append(err)

# this converts the api.login() call to a Twisted thread.
# api.login() should return True and is is equivalent to:
# api.service.login(username=self.username, password=self.password)
deferred = threads.deferToThread(api.login)
deferred.addCallbacks(handleResult, handleError)

reactor.run()

これは期待どおりに機能しapi.login()、ブロックするのではなく、呼び出しが完了するまで呼び出しの戻りを延期します。しかし、私が言ったように、それは正しく感じられません。

ヘルプ、ガイダンス、フィードバック、批判、侮辱、または完全な解決策を事前に感謝します。

更新:私が見つけた唯一の解決策はtwisted-sudsです。これは、Twistedで動作するように変更されたSudsのフォークです。

4

1 に答える 1

13

Twistedのコンテキストでのトランスポートのデフォルトの解釈は、おそらくの実装ですtwisted.internet.interfaces.ITransport。このレイヤーでは、基本的に、ある種のソケットを介して送受信されるrawバイトを処理します(UDP、TCP、およびSSLが最も一般的に使用される3つです)。これは、SUDS / Twisted統合ライブラリが実際に関心を持っているものではありません。代わりに、必要なのは、SUDSが必要な要求を行うために使用でき、SUDSが結果を判別できるようにすべての応答データを提示するHTTPクライアントです。だった。つまり、SUDSはネットワーク上の生のバイトを実際には気にしません。気になるのはHTTPリクエストとレスポンスです。

(Twisted Web SOAP APIのクライアント部分)の実装を調べると、twisted.web.soap.Proxy実際にはあまり効果がないことがわかります。SOAPpyに接着するのは約20行のコードですtwisted.web.client.getPage。つまり、上記で説明した方法で、SOAPpyをTwistedに接続しています。

SOAPpy.buildSOAP理想的には、SUDSはとのラインに沿ってある種のAPIを提供SOAPpy.parseSOAPRPCします(おそらく、APIはもう少し複雑になるか、さらにいくつかのパラメーターを受け入れます-私はSOAPの専門家ではないので、SOAPpyの特定のAPIかどうかはわかりません重要なものが欠けていますが、基本的な考え方は同じである必要があります)。twisted.web.soap.Proxy次に、代わりにSUDSに基づいたようなものを書くことができます。twisted.web.client.getPage要求または応答に関する十分な情報を十分に制御できない場合はtwisted.web.client.Agent、代わりに使用することもできます。これは最近導入され、要求/応答プロセス全体をより詳細に制御できます。getPageしかし、繰り返しになりますが、これは現在のコードとまったく同じ考え方であり、より柔軟で表現力豊かな実装です。

のAPIドキュメントを見たところClient.options.transport、SUDSトランスポートは基本的にHTTPクライアントのようです。この種の統合の問題は、SUDSが要求を送信し、すぐに応答を取得できるようにすることです。Twistedは主にコールバックに基づいているため、TwistedベースのHTTPクライアントAPIはSUDSにすぐに応答を返すことはできません。Deferred(または同等の)のみを返すことができます。

これが、関係が逆転した場合に物事がうまく機能する理由です。SUDSにHTTPクライアントを提供する代わりに、SUDSとHTTPクライアントを3番目のコードに提供し、相互作用を調整します。

ただし、ツイストベースのSUDSトランスポート(別名HTTPクライアント)を作成して機能させることは不可能ではないかもしれません。Twistedが主にDeferred(コールバックとも呼ばれる)イベントを公開するために使用するという事実は、これが機能する唯一の方法であることを意味するわけではありません。などのサードパーティライブラリを使用するgreenletことで、コルーチンベースのAPIを提供できます。この場合、非同期操作のリクエストには、あるコルーチンから別のコルーチンへの実行の切り替えが含まれ、イベントは元のコルーチンに切り替えることで配信されます。これを行うことができるcorotwineと呼ばれるプロジェクトがあります。それはかもしれませんこれを使用して、SUDSに必要な種類のHTTPクライアントAPIを提供することができます。ただし、それは保証されません。以前は存在しなかった場所にコンテキストスイッチが突然挿入されたときに、SUDSが壊れないかどうかに依存します。これはSUDSの非常に微妙で壊れやすいプロパティであり、将来のリリースでSUDS開発者が簡単に(意図せずにでも)変更できるため、今すぐ機能させることができたとしても、おそらく理想的なソリューションではありません(この種の構成でコードをテストして、コードが引き続き機能することを確認するという約束の形で、SUDSメンテナから協力を得てください)。

余談ですが、Twisted WebのSOAPサポートがまだSOAPpyに基づいており、2年近く変更されていない理由は、SOAPpyの明確な代替品がこれまでにないためです。多くの候補があります(Python用にどのSOAPクライアントライブラリが存在し、それらのドキュメントはどこにありますか?それらのいくつかをカバーしています)。物事が落ち着いたら、Twistedの組み込みSOAPサポートを更新してみるのが理にかなっているかもしれません。それまでは、これらの統合ライブラリを個別に実行する方が理にかなっていると思います。そうすれば、より簡単に更新できるため、Twisted自体が、誰も望まないさまざまなSOAP統合の山になってしまうことはありません(現在の状況では、誰も望まないSOAP統合モジュールが1つだけあります)。

于 2010-04-20T00:48:02.780 に答える