2K Views
March 26, 24
スライド概要
[第9回大阪SAS勉強会]小澤 義人
SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです
SAS and API Application Programming Interface Program を簡単にしたいなとの思惑で複雑になってしまう仕組み。
本日の内容 スライドが細かいので、中身はスキップしていきます。 APIって何? 1)APIって何?(全体像) 2)APIって何? 少し具体的にしてみましょう。 ウェブAPI(Web API): ライブラリAPI: OSレベルのAPI: 3)図示 OSレベルのAPI: ライブラリAPI: ウェブAPI(Web API): 4)本題 1. Web API 共通事項 2. 翻訳 API をつかってみる (Deepl翻訳) 3. CDISC LIBRARY API を使ってみる。 5)終わり
APIって何?(全体像) ChatGPTに聞いてみました。 API(Application Programming Interface)は、 プログラム同士が相互に通信するためのインターフェースや手段を提供するものです。 APIは、ソフトウェアコンポーネントが他のコンポーネントと対話するための約束や規約を定義し、それを通じて情報やサービスをやり取りします。 1 APIは、さまざまな目的で使用されます。 以下はそのいくつかの例です: ウェブAPI(Web API): ウェブAPIは、ウェブ上でサービスを提供するために使用されます。 これは、HTTPプロトコルを通じてデータを送受信し、通常はJSONやXML形式で情報をやり取りします。 例えば、Google Maps APIは地図データを提供し、Twitter APIはツイートの取得や投稿を可能にします。 2 ライブラリAPI: プログラミング言語やフレームワークが提供する関数やメソッドなどの集合体もAPIと呼ばれます。 開発者はこれらのAPIを使用して、特定の言語やフレームワークでの機能を実現できます。 3 OSレベルのAPI: オペレーティングシステムは、アプリケーションがハードウェアやシステムリソースにアクセスできるようにするためのAPIを提供します。 例えば、Windows APIやPOSIX APIがこれに該当します。 ★ APIは、開発者が他のソフトウェアやサービスと効果的に対話し、連携するための効果的な手段を提供することで、 ソフトウェア開発やシステム統合の際に非常に重要な役割を果たしています。
APIって何? 少し具体的にしてみましょう。 説明: 1 ウェブAPI(Web API): ・ Google Maps APIは地図データを提供し ・ Twitter APIはツイートの取得や投稿を可能にします。 => 今回は SAS で 下記2つのWeb APIを使ってみます。 1. 翻訳 API をつかってみる (Deepl) 2. CDISC LIBRARY API を使ってみる。 独り言: 1) SAS と Python 2) SAS と R <= DATASET JSON など扱うときには Python をCall したほうが良いのかな。 <= R も使ってみたいな。 API?ではない?それともAPI? Viya になったら簡単になるのかな。 =>まあでも。。。 手になじむと SASは 便利かな。
APIって何? 少し具体的にしてみましょう。 説明: 2 ライブラリAPI: ・プログラミング言語やフレームワークが提供する関数やメソッドなどの集合体もAPIと呼ばれます。 ・開発者はこれらのAPIを使用して、特定の言語やフレームワークでの機能を実現できます。 => 実際には、個別のライブラリを Call するよりは Comamnd.com , cmd.com , bash , shell 等の 汎用的な プログラムを呼び出すことが多いです。 ・SAS では SYSTEM関数 、 CALL SYSTEMルーチン などで Shell を呼び出すことで 動作している OSに依存しないプログラムが書けます。 ひと昔前はEXCEL の DDEを使った プログラムを書くことが多かったです。 1. X コマンドなどで Ecxcel を起動して SASのコマンドを受ける体制を整えて。 2. Filename DDE ‘system|excel’ のような感じで excel にコマンドを送っていました。 DDEが Windows 3.1 の機能(API と言っていいか否か不明ですが。。。)ですので このようなプログラムは OS 依存(Windows 3.1 の機能である DDE を有した環境) でないと実行できませんでした。 ライブラリAPIとOSレベルAPIの混在のような感じです。 3. Windows 3.1 の DDE はWindows から Excel などのアプリケーションにデータを送り込むだけ(または取り込むだけ)の機能しかなかったように思います。 タイミングや実行環境のチェックのプログラムや対応が必要でした。 タイミングの処理のため適当な時間 SASで時間をつぶす( x= sleep (10) )とか、起動した excel には触らないとか、SASProgram が複雑になってました。 4. OLEなどで起動しているアプリケーションと起動IDを交換して、起動状況を確認することができるようになったのですが・・・ あまり OLEを使ったProgram はSAS では浸透しなかったように感じます。 ただ、オブジェクト指向のプログラムの始まりですので、SAS/AFでは SCL (Screen Control Language)が搭載され 概念的にはVBA のようなオブジェクト指向のプログラムが書ける のですが、記法としてVBA より書きにくいものであったり、情報が少なく何かをしてもすぐ壁に突 き当たってしまいます。
APIって何? 少し具体的にしてみましょう。 説明: 3 OSレベルのAPI: Windows API は Windows のネイティブの機能を直接呼び出せるため,痒いところに手の届くアプリケーションを開発でき ます。でも OSレベルのAPI は複雑なので簡単なアプリケーションの開発でも苦労を伴います。 MS-DOS以前の PC98 では BIOS割り込みに INT 1Bh (DISK BIOS) (INT というのが割り込み) 割り込み Table の 1Bh 番地を CALL する(そこに JMPする)とその周りの引数に応じた対応をします。 => フロッピーディスコのコピーツールやコピーガードを外す際に INT 1B 周りを調査するもので、PC98の割り込み テーブルが広く知られるようになったのではないでしょうか。(INT 1B はOSの公開というよりはPC98の仕様 ) MS-DOS では割り込み Table の 21h 番地が整備されました(INT21H で Call するのが MS-DOS というイ メージでした) これは、公開された仕様です。 => INT21 を含む種々の公開仕様(API)を元にサードパーティでいろいろなソフトが作られています。 遠い昔の記憶なので、若干あいまいですがお許しください。
APIって何? 説明: SAS OSレベルのAPI:
APIって何? 説明: SAS ライブラリAPI:
APIって何? 最近、 SASpy というのを聞いたことがありますか? これは SASシステムのための Python APIですね。 説明: SASPy — saspy 5.4.4 documentation (sassoftware.github.io) https://support.sas.com/en/software/saspy.html SAS ライブラリAPI:
APIって何? 説明: 本日、SASでやってみました~ 的にご紹介するのが Web API です。 SAS ウェブAPI(Web API): HTTP:~~~~~~~
Web API 共通事項 1)接続先の URL を確認しよう。 2)接続の手順を確認しよう。 3)API-Key などのパスワードみたいなものが必要です。 4)いきなり SAS は難しいのでまずは curl コマンドで確認。 下記のような Web ページを眺めて、Curl の使い方に慣れておいたほうが何かと便利です。 curl コマンド 使い方メモ (https://qiita.com/yasuhiroki/items/a569d3371a66e365316f) いつも ブラウザに入力している URL を コマンドラインから打ち込んでみると、画面にレスポンスか帰ってきます。 curl https://www.yahoo.co.jp curl https://www.google.com >> c:\Yahoo.html ファイルにしたければリダイレクトをしておけばファイルが作成 >> c:\Google.html curl –help でオプションがリストされます。 HTTP/2 や HTTP/1.1 と Version の異なるプロトコルが混在しています。 https://www.kagoya.jp/howto/it-glossary/security/http-2/
Web API 共通事項 HTTP/2 や HTTP/1.1 と Version の異なるプロトコルが混在しています。 https://www.kagoya.jp/howto/it-glossary/security/http-2/ 翻訳 API では http/2 が必要なので、curl も http/2 対応のものに Update しましょう。 使われている curl の確認には 下記のようなコマンドが使えます。 curl -si https://curl.se -o/dev/null -w '%{http_version}\n’ 私の環境ではデフォルトでは HTTP/1.1 でした。 (curl 8.4.0 (Windows) libcurl/8.4.0 Schannel WinIDN) Http/2対応の ものに変更しました。 (同じ Versionですけど 8.4.0 (x86_64-w64-mingw32)
翻訳 API をつかってみる (Deepl) https://www.deepl.com/ja/docs-api まずはこのページの例を動かしましょう。 最初は Curl で動かします。 無料版のAPIをして 認証キーを入手しました。 無料版なので1か月 50万もじまでです。 SAS でごりごり動かすと、すぐ文字制限に到達してしまいます。 APIの Test としては分かりやすいですが、業務で使うなら 有料版?
やってみよう。 Deepl 翻訳 Curl
例
curl -X POST 'https://apifree.deepl.com/v2/translate' \
--header ‘Authorization: DeepL-Auth-Key
????????-????-???? –????-????????????:fx’ \
--data-urlencode 'text=Hello, world!' \
--data-urlencode 'target_lang=DE'
EXAMPLE RESPONSE
{
"translations": [
{
"detected_source_language": "EN",
"text": "Hallo, Welt!"
}
]
}
1) Windows 環境の Command.com では文字区切りは
シングルクオートではなくダブルクオートでした。
2) Windows 環境の Command.com では
Multiline は扱えませんでした。
curl -X POST "https://api-free.deepl.com/v2/translate" -header "Authorization: DeepL-Auth-Key ????????-????-????
–????-????????????:fx" --data-urlencode "text=Hello,
world!" --data-urlencode "target_lang=DE"
1) 英語(EN)から 日本語(JA)にしてみます。
curl -X POST "https://api-free.deepl.com/v2/translate" -header "Authorization: DeepL-Auth-Key ????????-????-????
–????-????????????:fx " --data-urlencode "text=Hello,
world!" --data-urlencode "target_lang=JA"
やってみよう。 Deepl 翻訳 Curl ファイルに書き出し
前の例ではコマンド内に "text=Hello, world!" というテキストを翻訳しました。
curl -X POST "https://api-free.deepl.com/v2/translate" --header "Authorization: DeepL-Auth-Key ????????-????-???? –????-????????????:fx " --data-urlencode "text=Hello, world!" --dataurlencode "target_lang=JA"
SASで扱うことと、コマンドラインの行数制限を考えると、翻訳の文書はファイルで送りたいです。
「Upload and Translate a Document」のコマンドをTestしてみます。
ファイル、ここでは C:\test\E_J.txt のファイルを翻訳します。 中身は [from file : Hello, world! ]です(文字数制限があるので簡単な物にしました。
curl -X POST "https://api-free.deepl.com/v2/document" --header "Authorization: DeepL-Auth-Key ????????-????-???? –????-????????????:fx " --form "file=@C:\test\E_J.txt" --form
"source_lang=EN" --form "target_lang=JA"
Uploadが成功すると ドキュメント番号とドキュメントキーが返ってきます。
{"document_id":"BB18858C48653C359ABDA058F3439C1F","document_key":"84EAF22BED15C257A85AA1963B14840A1129F367AFB276DE518C7182C199A1F6"}
このドキュメントキーを使って翻訳の状態を確認します。 Check Document Status
curl -X POST "https://api-free.deepl.com/v2/document/BB18858C48653C359ABDA058F3439C1F" --header "Authorization: DeepL-Auth-Key ????????-????-???? –????-????????????:fx " --dataurlencode "document_key=84EAF22BED15C257A85AA1963B14840A1129F367AFB276DE518C7182C199A1F6"
{“document_id”:“BB18858C48653C359ABDA058F3439C1F”,“sta tus”:“done”,“billed_characters”:25}
翻訳終了です。
WEB URL はだめだった~
結局 Windows /or os Shell から Curl をCallして情報を入手
=> Curl の力を借りたライブラリAPI:って感じかな
できない
libname jsn ;
filename resp temp ;
proc http
method="post"
url="https://api-free.deepl.com/v2/document/BB18858C48653C359ABDA058F3439C1F"
out=resp;
headers
"Authorization"="DeepL-Auth-Key ????????????????????????????????????:fx"
"Accept"="application/json" ;
;
data-urlencode
"document"="document_key
84EAF22BED15C257A85AA1963B14840A1129F367AFB276DE518C7182C199A1F6"
;
libname jsn JSON fileref=resp;
filename resp ;
こんな感じで対応
filename zz 'm:\zz.bat' ;
data _null_ ;
length xx $1000. ;
file zz ;
Xx='curl –X POST https://api-free.deepl.com/v2/document/BB18858C48653C359ABDA058F3439C1F' ;
put xx @ ;
xx='--header "Authorization: DeepL-Auth-Key ????????????????????????????????????:fx " --dataurlencode
"document_key=84EAF22BED15C257A85AA1963B14840A1129F367AFB276DE518C7182C199A1F6"' ;
put xx ;
run ;
* x 'm:\zz.bat' ;
filename listing pipe "m:\zz.bat" ;
data null ;
length inf $2000. ;
infile listing ;
input ;
inf= _infile_ ;
run ;
data null ; set null ;
retain flg 0 ;
if substr ( left (inf) , 1,1) ='{' then flg=1 ;
run ;
data null ; set null ;
if flg=1 then output ;
run ;
だめだった~: SASは HTTP/1.1 準拠 https://documentation.sas.com/doc/en/pgmsascdc/9.4_3. 5/proc/n0t7v16eitluu2n15ffpfeafqszs.htm HTTP/2 は使えない~
それでも一連のプログラムを作成してみました。(1/3)
Shell Call は xから %sysexec に変更しています。
** https://blogs.sas.com/content/sgf/2020/07/30/curl-to-proc-http/ ;
%*--------------------------------;
%* Deepl 翻訳 ;
%*--------------------------------;
%*--------------------------------;
%*Upload and Translate a Document ;
%*--------------------------------;
%global respF ;
%let apik= ????????????????????????????????????:fx;
%let xfname =c:\test\E_J ;
%let xext =txt ;
%let xfile =&xfname..&xext.
;
%let outfile =&xfname._JP.&xext. ;
%let respF =c:\test\response.txt ;
%* ファイル削除 ;
data _null_;
fname="TMP" ;
rc=filename(fname,"&respF." );
if rc = 0 and fexist(fname) then
rc=fdelete(fname);
run;
%*------------------------------------------------------------------*翻訳ファイルを UPLOAD の cURL コマンド
curl -X POST "https://api-free.deepl.com/v2/document" --header "Authorization: DeepL-Auth-Key &apik." --form "file=@m:\xx.txt" --form "source_lang=EN" --form "target_lang=JA"
* Response ;
{"document_id":"4BEDB9C25FA18321FFD731E624BC1CA4","document_key":"6BE101ADBDB9262B7A63CDA3C3BC7B72CAA36A226 9932306FB84C38CA38E26F6"}
-------------------------------------------------------%;;
data _null_;
%sysexec curl -Ss -o "&respF." -X POST "https://api-free.deepl.com/v2/document" --header "Authorization: DeepL-Auth-Key &apik." --form "file=@&xfile." --form "source_lang=EN" --form "target_lang=JA" ;
run;
それでも一連のプログラムを作成してみました。(2/3) %macro waitresp ( _respF=&respF. , sleepsec=6 , noofwait=10 ) ; %local _respF ; %* response 待ち、6秒× 10回 ; data _null_; fname="TMP" ; do waitresp=1 to &noofwait. ; rc=filename(fname,"&_respF." ); put rc=; if rc = 0 and fexist(fname) then stop ; else do ;x=sleep(&sleepsec.) ; end ; put waitresp ; end ; run; filename tmp ; %mend ; %waitresp ; このサンプルでは下記のようなファイルが 作成されます。 Excel 、Word 、PDFでもOKだと思います。 翻訳前 翻訳後 %* response をデータにする ; libname res json "&respF." ; data docIDALL ; set res.alldata ; run ; data docID ; set res.root ; run ; libname res ; proc sql noprint ; select document_id , document_key into:document_idx, :document_keyx from docID quit ; %put &document_idx. &document_keyx ; %* ファイル削除 ; data _null_; fname="TMP" ; rc=filename(fname,"&respF." ); if rc = 0 and fexist(fname) then rc=fdelete(fname); run; このプログラムでは 一度ダウンロードされると 上書きされてしまうので要注意! Document already downloaded
それでも一連のプログラムを作成してみました。(3/3)
%*--------------------------------;
%*Check Document Status ;
%*--------------------------------;
%*------------------------------------------------------------------curl -X POST "https://api-free.deepl.com/v2/document/4BEDB9C25FA18321FFD731E624BC1CA4" --header "Authorization: DeepL-Auth-Key &apik." --data-urlencode "document_key=6BE101ADBDB9262B7A63CDA3C3BC7B72CAA36A2269932306FB84C38CA38E 26F6"
{"document_id":"4BEDB9C25FA18321FFD731E624BC1CA4","status":"done","billed_characters":42436}
-------------------------------------------------------%;;
data _null_;
%sysexec curl -Ss -o "&respF." -X POST "https://api-free.deepl.com/v2/document/&document_idx." --header "Authorization: DeepL-Auth-Key &apik." --data-urlencode"document_key=&document_keyx." ;
run;
%waitresp ;
%* response をデータにする ;
libname res json "&respF." ;
data docStatusAll ; set res.alldata ; run ;
data docStatus ; set res.root ; run ;
libname res ;
proc sql noprint ;
select document_id , status into:document_idxx , :statusxx from docStatus ;
quit ;
/*** STATUS =ERROR STATUS=translating seconds_remaining=1023 STATUS=done billed_characters=
**/
%put &document_idxx. &statusxx. ;
%* ファイル削除 ;
data _null_; fname="TMP" ; rc=filename(fname,"&respF." ); if rc = 0 and fexist(fname) then
rc=fdelete(fname);
run;
%macro ckstatus ( ck=&statusxx.) ;
%if "&ck."="done" %then %do ;
%*--------------------------------;
%*Download Translated Document ;
%*--------------------------------;
%put "&outfile." ;
%put "&ck." ;
%put "&document_idxx." ;
%put "&document_keyx." ;
data _null_;
%sysexec curl -Ss -o "&outfile." -X POST "https://api-free.deepl.com/v2/document/&document_idxx./result" --header "Authorization: DeepL-Auth-Key &apik." --data-urlencode"document_key=&document_keyx." ;
run;
%* %waitresp ;
%end ;
%else %do ;
%put 'まだ翻訳が終わってません ' ;
%end ;
%mend ;
%ckstatus ;
もっと良い例は? Web APIっぽいのはないかな???? SASで直接使いたい
CDISC LIBRARY API を使ってみる。(1/5) SASで直接使いたい Web API(情報収集&APIKey入手) API Portal CDISC Library Browser CDISC LIBRARY まずは 情報収集 (ユーザー登録などを済ませてから API Portalにアクセス。) CDISC Data Standards Browser https://api.developer.library.cdisc.org/ API Key API Portal から API Key を入手します。 API Tester API Documentation How-to articles
CDISC LIBRARY API を使ってみる。(2/5) Program sample 入手 How-to articles Getting Started: Programmatically connect to CDISC Library API Python SAS R Java XQuery プログラム中のAPI Keyは例示サンプルです、API key の取得は必須です。
CDISC LIBRARY API を使ってみる。 (3/5)
Program 実行
%let apik=???????????????????????????????? ;
filename response TEMP;
proc http
url='https://library.cdisc.org/api/mdr/products'
out=response;
headers
/* fictitious API key used, real one can be obtained through API
Management Developer Portal */
/* change to "application/xml" for response in XML format */
"api-key"="&apik."
"Accept"="application/json";
run;
data _null_;
infile response;
input;
put _infile_;
run;
SAS のLogWindowにJson データが出力されています。
CDISC LIBRARY API を使ってみる。 (4/5) Requestの URLは? API Tester で Request URLを探す。 ① 例えば、CT(Controlled Terminology )を入手) ③ ① CDISC LIBRARY API ② GET /mdr/ct/packages/{package} package には SDTM-CT-2019-12-20 のような記載、 現在最新は sdtmct-2023-12-15 ・大文字小文字の Case sencitive ではないようです。 ③ うまくいけば、青色の結果が返ってきます。 ②
CDISC LIBRARY API を使ってみる。 (5/5)
Program マクロ化
①マクロ定義 CDISCAPI
%macro CDISCAPI ( xurl , apikey=&apik. ) ;
filename resp TEMP ;
proc http
url="&xurl."
out=resp;
headers
/* fictitious API key used, real one can be obtained through API Management Developer Portal */
/* change to "application/xml" for response in XML format */
"api-key"="&apikey."
"Accept"="application/json";
run;
/* Assign a JSON library to the HTTP response */
libname jsn JSON fileref=resp;
proc sql ;
create table _tname as
select * from sashelp.vtable where libname='JSN'
;
quit ;
filename ff catalog 'work.tmp.json_sas.source' ;
data _null_ ; set _tname ;
file ff ;
put 'data ' memname ' ; set ' libname +(-1) '.' memname ' ; run ;' ;
run ;
%inc ff ;
filename ff ;
libname jsn ;
filename resp ;
%mend ;
③データセットができています。
Codelistcode 1081 レコードと
codelistcodeを親に持つ
CTコードの1081個のデータセット
②マクロ利用 CDISCAPI
(CT(Controlled Terminology )を入手)
libname API ‘C:\test’ ; * 保存先 ;
%global apik ;
%let apik=???????????????????????????????? ;
%macro hang ; proc datasets lib=work kill NOLIST; quit; %mend ;
%hang ; %CDISCAPI ( https://api.library.cdisc.org/api/mdr/ct/packages/sdtmct-2023-12-15 ) ;
data api.CodelistsCode_20231215x ;set Codelists ;
codelistcode
= conceptId
;
CodelistExtensible = extensible
;
CodelistName
= definition
;
CDISCSubmissionValue = submissionValue ;
keep
codelistcode
CodelistExtensible
CodelistName
CDISCSubmissionValue
;
run ;
/* 個々のコードリスト確認(Test)
%hang ; %CDISCAPI ( https://library.cdisc.org/api/mdr/ct/packages/sdtmct-2023-12-15/codelists/C67152 ) ;
data api.term_C67152 ;set root ; run ;
*/
/* 全部のコードリスト入手 */
filename tmp catalog 'work.tmp.tmp.source' ;
data _null_ ; set api.CodelistsCode_20231215 ;
file tmp ;
put '%hang ; %CDISCAPI ( https://api.library.cdisc.org/api/mdr/ct/packages/sdtmct-2023-12-15/codelists/' codelistcode
' ) ;' ;
put 'data api.term_' codelistcode +(-1) '_' CDISCSubmissionValue ' ;length codelistcode $20. ; set terms ; codelistcode="'
codelistcode '" ; run ;' ;
run ;
%inc tmp ;
filename tmp;
終わり 終わりに、最近では Rest [ful] API というのも耳にしますね。 REST(Representational State Transfer)とは Wikipedia(https://ja.wikipedia.org/wiki/Representational_State_Transfer)では、 Representational State Transfer (REST、レスト) は、ウェブAPI(ウェブアプリケーションプログラ ミングインタフェース)の定義に使用されるアーキテクチャスタイル(共通仕様)であり、同時 にウェブのような分散ハイパーメディアシステムのためのソフトウェアアーキテクチャのスタイ ルのひとつでもある。 この語はHTTPプロトコル規格の主要著者の一人であるロイ・フィールディング(英語版)がウェ ブについて書いた2000年の博士論文で初めて現れ、ネットワーキングコミュニティの中ですぐに 広く使われることになった。 ~~~~~~~~ 以下略 コメント:単なるWeb APIよりは REST APIのほうが、仕様がしっかりしているのでプログラムは使いまわせる?
ありがとうございました。 ご質問、ご意見、提案等があればお気楽にご連絡ください。 ********************************************** 小澤 義人 国立大学法人千葉大学 医学部附属病院 特任助教 臨床試験部生物統計室 E-mail: [email protected] *********************************************