前回はIronPythonを捨てて、RESTを使ってPythonと連携しました。
Introduction
C#からPythonで公開したREST APIを呼び出すことには成功しました。
逆にC#で公開したREST APIを呼び出すことも可能です。
定期的にPython側での処理結果をC#側にプッシュするような形態のシステムもあり得ますので、PythonからC#への通信方法を知ることも有用でしょう。
今回のソースは下記になります
Python
requestsインストール
requestsは「人間のためのHTTP」と銘打った、極めてシンプルで洗練されたHTTPライブラリです。
インストールもお馴染みのpipで簡単。
1 | $ python -m pip install requests |
以上でインストールは完了です。
ソース
前回のソースに手を加えた感じです。
1 | from flask import Flask |
getメソッド内で、DateTimeServiceClient._sendメソッドを呼び出します。
_sendメソッドは、外部のREST APIに対してPOSTで現在時刻を渡します。
つまり、外部(C#)から自身のREST APIを呼ばれている最中に、外部(C#)のREST APIを呼び出します。
重要なことですが、
- headersはpostメソッドに渡してください
- paramsのdateTimeキーの文字列を間違えないでください
- postメソッドの第一引数はC#側ときちんと一致させること
これらが守られないと、クラッシュしたり、正しく動きません。
Python側は以上です。
C#
インストールするライブラリは前回と同じです。
ソース
WPFです。Xaml側は省略します。
Xamlは、Python側のREST APIを呼び出すButton、Python側から受け取る現在時刻情報を追加するListBoxです。
ViewModelもButtonに対応するコマンドと現在時刻のコレクションだけです。
まずは、公開するREST APIです。
1 | using System; |
1 | using System; |
肝はSendメソッドに付与されたWebInvoke属性です。
プロパティは重要ですが、UriTemplateプロパティの値は特に重要です。
Sendメソッドの名前と、UriTemplateプロパティのSendは一致させる必要はありませんが、UriTemplateプロパティのSendはPython側で、postメソッドで指定した値と一致させます。
同様に、dateTimeもPython側のparamsのキーと一致させます。
ちなみに、UriTemplateプロパティのparamDateTimeの部分は、Sendメソッドの引数、paramDateTimeと一致させないと、アプリ起動時にクラッシュします。
Sendメソッドの中身は単純で、渡ってきた文字列をDateTime型に変換し、イベントを呼び出すだけです。
次にViewModelです。
1 | using System; |
MessageCommandがPython側のREST APIを呼び出します。
また、その呼び出しで、C#側のREST APIがPython側から実行され、Python側から渡ってきた時刻がResponsesコレクションに追加されます。
最後にViewModelLocatorです。
1 | /* |
WebServiceHostインスタンス生成時のUrlに注意するのと、IDateTimeServiceに対応する実際の型は、MinaViewModelに保持するインスタンスと、WebServiceHostで保持するインスタンスは同一であることに注意します。
ポート番号も一致させます。
C#は以上です。
テスト
実際に実行してみます。
C#側を起動する前に、PythonでRESTサービス側を起動しておいてください。
ボタンを押下すると、Python側から受け取った現在時刻が画面下部のListBoxに追加されていきます。
Conclusion
C#側のRESTを活用して、C#とPythonで双方向通信が可能になりました。
実はRESTを使用したアプリを作るのは初めてでした。
WebInvoke属性の値の設定で苦労しましたが、良い経験になりました。
Source Code
https://github.com/takuya-takeuchi/Demo/tree/master/WPF/05_WPF.Python5