組み込み Python の使用法
組み込み Python により、InterSystems IRIS アプリケーションをプログラミングするネイティブ・オプションとして Python を使用できるようになります。 組み込み Python を使用するのが初めてである場合は、まず "組み込み Python の概要" を参照し、その後組み込み Python のより詳細な説明として、このドキュメントをお読みください。
このドキュメントは組み込み Python について学習する人すべてに役立ちますが、理解するうえで ObjectScript についてのある程度の知識を持っていることが望ましいでしょう。InterSystems IRIS および ObjectScript に不慣れな Python 開発者の場合、"サーバ側プログラミングの入門ガイド" も参照してください。
前提条件
組み込み Python の使用に必要な Python のバージョンは、実行しているプラットフォームによって異なります。ほとんどの場合は、お使いのオペレーティング・システムの Python の既定バージョンです。オペレーティング・システムと対応する Python のサポート対象バージョンの完全なリストは、"その他のサポート対象機能" を参照してください。組み込み Python の使用時に異なるバージョンの Python を使用すると、エラーが発生します。
Microsoft Windows では、InterSystems IRIS インストール・キットによって、組み込み Python 専用の正しいバージョンの Python (現在は 3.9.5) がインストールされます。開発マシンを使用していて、Python を一般用途に使用したい場合は、この同じバージョンを https://www.python.org/downloads/Opens in a new tab からダウンロードしてインストールすることをお勧めします。
多くの UNIX ベースのオペレーティング・システムでは、既に Python がインストールされています。インストールする必要がある場合は、パッケージ・マネージャによりご使用のオペレーティング・システムに推奨されるバージョンを使用してください。以下に例を示します。
-
macOS : Homebrew (https://formulae.brew.sh/formula/python@3.9Opens in a new tab) を使用して Python 3.9 をインストール
-
Ubuntu : apt-get install python3
-
Red Hat Enterprise Linux または Oracle Linux : yum install python3
-
SUSE : zypper install python3
“Python をロードできませんでした” というエラーが表示された場合は、システムに Python がインストールされていないか、Python の予期しないバージョンが検出されたかのどちらかです。"その他のサポート対象機能" を調べて、必要なバージョンの Python がインストールされていることを確認し、必要に応じて、上記のいずれの方法で Python をインストールまたは再インストールしてください。
コンピュータに複数のバージョンの Python がインストールされている場合、コマンド行から組み込み Python の実行を試行すると、irispython は最初に検出された python3 実行可能ファイル (PATH 環境変数よって決まる) を実行します。正しいバージョンの実行可能ファイルが最初に検出されるように、パスのフォルダが適切に設定されていることを確認してください。irispython コマンドの使用の詳細は、"コマンド行からの Python シェルの開始" を参照してください。
UNIX ベースのシステムでは、pip3 コマンドを使用して Python パッケージをインストールできます。pip3 をまだインストールしていない場合は、システムのパッケージ・マネージャでパッケージ python3-pip をインストールしてください。
組み込み Python の実行時に IRIS_ACCESSDENIED エラーが発生しないようにするには、%Service_Callin を有効にします。管理ポータルで、[システム管理]→[セキュリティ]→[サービス] に移動し、[%Service_CallIn] を選択し、[サービス有効] ボックスにチェックを付けます。
組み込み Python の実行
このセクションでは、組み込み Python を実行するいくつかの方法を説明します。
これらすべての方法で、iris Python モジュールをインポートしてそのメソッドを使用することで、InterSystems IRIS API を呼び出すことができます。
Python シェルから実行
インターシステムズのターミナル・セッションまたはコマンド行から Python シェルを開始できます。
ターミナルからの Python シェルの開始
インターシステムズのターミナル・セッションから Python シェルを開始するには、%SYS.PythonOpens in a new tab クラスの Shell() メソッドを呼び出します。これにより、Python インタプリタがインタラクティブ・モードで起動します。ターミナル・セッションからユーザとネームスペースが Python シェルに渡されます。
コマンド quit() を入力して、Python シェルを終了します。
以下の例は、ターミナル・セッションの USER ネームスペースから Python シェルを起動します。これは、フィボナッチ数列の最初の数個の数字を出力し、その後 InterSystems IRIS の %SYSTEM.OBJ.ShowClasses() メソッドを使用して現在のネームスペース内のクラスのリストを出力します。
USER>do ##class(%SYS.Python).Shell()
Python 3.9.5 (default, Jul 6 2021, 13:03:56) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
>>> a, b = 0, 1
>>> while a < 10:
... print(a, end=' ')
... a, b = b, a+b
...
0 1 1 2 3 5 8 >>>
>>> status = iris.cls('%SYSTEM.OBJ').ShowClasses()
User.Company
User.Person
>>> print(status)
1
>>> quit()
USER>
メソッド %SYSTEM.OBJ.ShowClasses() は、InterSystems IRIS の %StatusOpens in a new tab の値を返します。この場合、1 はエラーが検出されなかったことを意味します。
%SYS.PythonOpens in a new tab クラスの Shell() メソッドを使用した Python シェルの実行時に、iris モジュールを明示的にインポートする必要はありません。続行して、モジュールを使用してください。
コマンド行からの Python シェルの開始
irispython コマンドを使用して、コマンド行から Python シェルを開始します。これは、ターミナルからのシェルの開始とほぼ同様に機能しますが、InterSystems IRIS のユーザ名、パスワード、およびネームスペースを渡す必要があります。
以下の例は、Windows コマンド行から Python シェルを起動します。
C:\InterSystems\IRIS\bin>set IRISUSERNAME = <username>
C:\InterSystems\IRIS\bin>set IRISPASSWORD = <password>
C:\InterSystems\IRIS\bin>set IRISNAMESPACE = USER
C:\InterSystems\IRIS\bin>irispython
Python 3.9.5 (default, Jul 6 2021, 13:03:56) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
UNIX ベースのシステムでは、set ではなく、export を使用します。
/InterSystems/IRIS/bin$ export IRISUSERNAME=<username>
/InterSystems/IRIS/bin$ export IRISPASSWORD=<password>
/InterSystems/IRIS/bin$ export IRISNAMESPACE=USER
/InterSystems/IRIS/bin$ ./irispython
Python 3.9.5 (default, Jul 22 2021, 23:12:58)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
import iris を実行しようとして、IRIS_ACCESSDENIED というメッセージが表示された場合は、%Service_Callin を有効にしてください。管理ポータルで、[システム管理]→[セキュリティ]→[サービス] に移動し、[%Service_CallIn] を選択し、[サービス有効] ボックスにチェックを付けます。
Python スクリプト・ファイル (.py) 内で実行
irispython コマンドを発行して、Python スクリプトを実行することもできます。
Windows システムで、以下のコードを持つ C:\python\test.py ファイルを見てみましょう。
# print the members of the Fibonacci series that are less than 10
print('Fibonacci series:')
a, b = 0, 1
while a < 10:
print(a, end=' ')
a, b = b, a + b
# import the iris module and show the classes in this namespace
import iris
print('\nInterSystems IRIS classes in this namespace:')
status = iris.cls('%SYSTEM.OBJ').ShowClasses()
print(status)
test.py は、コマンド行から以下のように実行できます。
C:\InterSystems\IRIS\bin>set IRISUSERNAME = <username>
C:\InterSystems\IRIS\bin>set IRISPASSWORD = <password>
C:\InterSystems\IRIS\bin>set IRISNAMESPACE = USER
C:\InterSystems\IRIS\bin>irispython \python\test.py
Fibonacci series:
0 1 1 2 3 5 8
InterSystems IRIS classes in this namespace:
User.Company
User.Person
1
UNIX ベースのシステムでは、set ではなく、export を使用します。
/InterSystems/IRIS/bin$ export IRISUSERNAME=<username>
/InterSystems/IRIS/bin$ export IRISPASSWORD=<password>
/InterSystems/IRIS/bin$ export IRISNAMESPACE=USER
/InterSystems/IRIS/bin$ ./irispython /python/test.py
Fibonacci series:
0 1 1 2 3 5 8
InterSystems IRIS classes in this namespace:
User.Company
User.Person
1
import iris を実行しようとして、IRIS_ACCESSDENIED というメッセージが表示された場合は、%Service_Callin を有効にしてください。管理ポータルで、[システム管理]→[セキュリティ]→[サービス] に移動し、[%Service_CallIn] を選択し、[サービス有効] ボックスにチェックを付けます。
InterSystems IRIS クラスのメソッド内で実行
Language キーワードを使用して、InterSystems IRIS クラス内で Python メソッドを記述できます。その後、ObjectScript で記述されたメソッドを呼び出す場合と同じように、メソッドを呼び出せます。
例えば、Python で記述されたクラス・メソッドを持つ以下のクラスを取り上げます。
Class User.EmbeddedPython
{
/// Description
ClassMethod Test() As %Status [ Language = python ]
{
# print the members of the Fibonacci series that are less than 10
print('Fibonacci series:')
a, b = 0, 1
while a < 10:
print(a, end=' ')
a, b = b, a + b
# import the iris module and show the classes in this namespace
import iris
print('\nInterSystems IRIS classes in this namespace:')
status = iris.cls('%SYSTEM.OBJ').ShowClasses()
return status
}
}
このメソッドは、ObjectScript から以下のように呼び出せます。
USER>set status = ##class(User.EmbeddedPython).Test()
Fibonacci series:
0 1 1 2 3 5 8
InterSystems IRIS classes in this namespace:
User.Company
User.EmbeddedPython
User.Person
USER>write status
1
または Python から以下のように呼び出せます。
>>> import iris
>>> status = iris.cls('User.EmbeddedPython').Test()
Fibonacci series:
0 1 1 2 3 5 8
InterSystems IRIS classes in this namespace:
User.Company
User.EmbeddedPython
User.Person
>>> print(status)
1
SQL 関数およびストアド・プロシージャ内で実行
組み込み Python を使用して SQL 関数またはストアド・プロシージャを記述することもできます。これには、以下のように CREATE 文で引数 LANGUAGE PYTHON を指定します。
CREATE FUNCTION tzconvert(dt TIMESTAMP, tzfrom VARCHAR, tzto VARCHAR)
RETURNS TIMESTAMP
LANGUAGE PYTHON
{
from datetime import datetime
from dateutil import parser, tz
d = parser.parse(dt)
if (tzfrom is not None):
tzf = tz.gettz(tzfrom)
d = d.replace(tzinfo = tzf)
return d.astimezone(tz.gettz(tzto)).strftime("%Y-%m-%d %H:%M:%S")
}
コードは Python の datetime および dateutil モジュールから関数を使用します。
プラットフォームによっては、datetime および dateutil モジュールが既定でインストールされていないことがあります。この例を実行して ModuleNotFoundError が発生した場合は、"Python ライブラリの使用" の説明に従って欠落しているモジュールをインストールします。
以下の SELECT 文は、SQL 関数を呼び出し、現在の日付/時刻を東部標準時から協定世界時 (UTC) に変換します。
SELECT tzconvert(now(), 'US/Eastern', 'UTC')
この関数は以下のような結果を返します。
2021-10-19 15:10:05
ObjectScript からの組み込み Python コードの呼び出し
このセクションでは、ObjectScript から組み込み Python コードを呼び出すいくつかの方法を説明します。
ObjectScript コードを呼び出すのとほとんど同じ方法で Python コードを呼び出せる場合もありますが、%SYS.PythonOpens in a new tab クラスを使用して 2 つの言語間のギャップを埋める必要がある場合もあります。詳細は、"ObjectScript と組み込み Python 間のギャップを埋める" を参照してください。
Python ライブラリの使用
組み込み Python では、何千もの便利なライブラリに簡単にアクセスできます。一般に "パッケージ" と呼ばれますが、これらは使用する前に Python Package Index (PyPIOpens in a new tab) から <installdir>/mgr/python ディレクトリにインストールする必要があります。
例えば、ReportLab Toolkit は、PDF およびグラフィックを生成するためのオープン・ソース・ライブラリです。以下のコマンドでは、パッケージ・インストーラ irispip を使用して Windows システムに ReportLab をインストールします。
C:\InterSystems\IRIS\bin>irispip install --target C:\InterSystems\IRIS\mgr\python reportlab
UNIX ベースのシステムでは、以下を使用します。
$ pip3 install --target /InterSystems/IRIS/mgr/python reportlab
パッケージをインストールしたら、%SYS.PythonOpens in a new tab クラスの Import() メソッドにより、それを ObjectScript コードで使用できます。
ファイルの場所を指定すると、以下の ObjectScript メソッド CreateSamplePDF() は、サンプルの PDF ファイルを作成し、その場所に保存します。
Class Demo.PDF
{
ClassMethod CreateSamplePDF(fileloc As %String) As %Status
{
set canvaslib = ##class(%SYS.Python).Import("reportlab.pdfgen.canvas")
set canvas = canvaslib.Canvas(fileloc)
do canvas.drawImage("C:\Sample\isc.png", 150, 600)
do canvas.drawImage("C:\Sample\python.png", 150, 200)
do canvas.setFont("Helvetica-Bold", 24)
do canvas.drawString(25, 450, "InterSystems IRIS & Python. Perfect Together.")
do canvas.save()
}
}
このメソッドの最初の行は、ReportLab の pdfgen サブパッケージから canvas.py ファイルをインポートします。コードの 2 番目の行は Canvas オブジェクトをインスタンス化し、その後続行して、InterSystems IRIS オブジェクトのメソッドを呼び出すのとほぼ同じ方法でそのメソッドを呼び出します。
その後、以下に示すように通常の方法でメソッドを呼び出せます。
do ##class(Demo.PDF).CreateSamplePDF("C:\Sample\hello.pdf")
以下の PDF が生成され、指定された場所に保存されます。
Python で記述された InterSystems IRIS クラス内でのメソッドの呼び出し
組み込み Python を使用して InterSystems IRIS クラスでメソッドを記述し、その後 ObjectScript で記述されたメソッドを呼び出すのと同じ方法で、ObjectScript からそのメソッドを呼び出すことができます。
次の例は usaddress-scourgify ライブラリを使用しています。このライブラリは Windows のコマンド行から以下のようにインストールできます。
C:\InterSystems\IRIS\bin>irispip install --target C:\InterSystems\IRIS\mgr\python usaddress-scourgify
UNIX ベースのシステムでは、以下を使用します。
$ pip3 install --target /InterSystems/IRIS/mgr/python usaddress-scourgify
以下のデモ・クラスには、米国の住所の各部分のプロパティと、Python で記述されたメソッドが含まれます。これは、usaddress-scourgify を使用して住所をアメリカ合衆国郵便公社の標準に従って正規化します。
Class Demo.Address Extends %Library.Persistent
{
Property AddressLine1 As %String;
Property AddressLine2 As %String;
Property City As %String;
Property State As %String;
Property PostalCode As %String;
Method Normalize(addr As %String) [ Language = python ]
{
from scourgify import normalize_address_record
normalized = normalize_address_record(addr)
self.AddressLine1 = normalized['address_line_1']
self.AddressLine2 = normalized['address_line_2']
self.City = normalized['city']
self.State = normalized['state']
self.PostalCode = normalized['postal_code']
}
}
住所の文字列を入力として指定すると、クラスの Normalize() インスタンス・メソッドは、住所を正規化し、各部分を Demo.Address オブジェクトのさまざまなプロパティに格納します。
このメソッドは以下のように呼び出せます。
USER>set a = ##class(Demo.Address).%New()
USER>do a.Normalize("One Memorial Drive, 8th Floor, Cambridge, Massachusetts 02142")
USER>zwrite a
a=3@Demo.Address <OREF>
+----------------- general information ---------------
| oref value: 3
| class name: Demo.Address
| reference count: 2
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| AddressLine1 = "ONE MEMORIAL DR"
| AddressLine2 = "FL 8TH"
| City = "CAMBRIDGE"
| PostalCode = "02142"
| State = "MA"
+-----------------------------------------------------
Python で記述された SQL 関数またはストアド・プロシージャの実行
組み込み Python を使用して SQL 関数またはストアド・プロシージャを作成する際、InterSystems IRIS は、他のメソッドを呼び出すのと同じように ObjectScript から呼び出せるメソッドを持つクラスを投影します。
例えば、このドキュメントで前述した例に示す SQL 関数は、tzconvert() メソッドを持つクラス User.functzconvert を生成します。これを ObjectScript から呼び出すには、以下のようにします。
USER>zwrite ##class(User.functzconvert).tzconvert($zdatetime($h,3),"US/Eastern","UTC")
"2021-10-20 15:09:26"
ここでは、$zdatetime($h,3) を使用して現在の日付と時刻が $HOROLOG 形式から ODBC 日付形式に変換されます。
任意の Python コマンドの実行
組み込み Python コードを開発またはテストしている際、任意の Python コマンドを ObjectScript から実行すると都合がよい場合があります。これは、%SYS.PythonOpens in a new tab クラスの Run() メソッドによって行えます。
例えば、このドキュメントの前半で使用した usaddress_scourgify パッケージからの normalize_address_record() 関数をテストしたいのに、その動作を思い出せない場合があるかもしれません。%SYS.Python.Run() メソッドを使用して、以下のようにターミナルから関数のヘルプを出力できます。
USER>set rslt = ##class(%SYS.Python).Run("from scourgify import normalize_address_record")
USER>set rslt = ##class(%SYS.Python).Run("help(normalize_address_record)")
Help on function normalize_address_record in module scourgify.normalize:
normalize_address_record(address, addr_map=None, addtl_funcs=None, strict=True)
Normalize an address according to USPS pub. 28 standards.
Takes an address string, or a dict-like with standard address fields
(address_line_1, address_line_2, city, state, postal_code), removes
unacceptable special characters, extra spaces, predictable abnormal
character sub-strings and phrases, abbreviates directional indicators
and street types. If applicable, line 2 address elements (ie: Apt, Unit)
are separated from line 1 inputs.
.
.
.
%SYS.Python.Run() メソッドは、成功した場合に 0 を返し、失敗した場合に -1 を返します。
相互運用プロダクション内での組み込み Python の使用法
InterSystems IRIS 内の相互運用プロダクション向けにカスタムのビジネス・ホスト・クラスやアダプタ・クラスを記述している場合、コールバック・メソッドはすべて ObjectScript で記述する必要があります。コールバック・メソッドは既定では何もしない継承メソッドですが、ユーザにより実装されるよう設計されています。ただし、コールバック・メソッドの ObjectScript コードは、Python ライブラリを活用したり、Python で実装されたその他のメソッドを呼び出すことができます。
以下の例は、受信メッセージから文字列値を取得し、Amazon Web Services (AWS) boto3 Python ライブラリを使用して、その文字列を Amazon Simple Notification Service (SNS) を介してテキスト・メッセージとして電話に送信するビジネス・オペレーションを示しています。この AWS ライブラリはここでの説明の範囲外ですが、この例では、OnInit() および OnMessage() コールバック・メソッドは ObjectScript で記述されているのに対し、PyInit() および SendSMS() のメソッドは Python で記述されていることがわかります。
/// Send SMS via AWS SNS
Class dc.opcua.SMS Extends Ens.BusinessOperation
{
Parameter INVOCATION = "Queue";
/// AWS boto3 client
Property client As %SYS.Python;
/// json.dumps reference
Property tojson As %SYS.Python;
/// Phone number to send SMS to
Property phone As %String [ Required ];
Parameter SETTINGS = "phone:SMS";
Method OnMessage(request As Ens.StringContainer, Output response As Ens.StringContainer) As %Status
{
#dim sc As %Status = $$$OK
try {
set response = ##class(Ens.StringContainer).%New(..SendSMS(request.StringValue))
set code = +{}.%FromJSON(response.StringValue).ResponseMetadata.HTTPStatusCode
set:(code'=200) sc = $$$ERROR($$$GeneralError, $$$FormatText("Error sending SMS,
code: %1 (expected 200), text: %2", code, response.StringValue))
} catch ex {
set sc = ex.AsStatus()
}
return sc
}
Method SendSMS(msg As %String) [ Language = python ]
{
response = self.client.publish(PhoneNumber=self.phone, Message=msg)
return self.tojson(response)
}
Method OnInit() As %Status
{
#dim sc As %Status = $$$OK
try {
do ..PyInit()
} catch ex {
set sc = ex.AsStatus()
}
quit sc
}
/// Connect to AWS
Method PyInit() [ Language = python ]
{
import boto3
from json import dumps
self.client = boto3.client("sns")
self.tojson = dumps
}
}
上記の OnMessage() メソッドのコードには、このドキュメントを印刷する際により適した書式設定とするために余分の改行が含まれています。
このルールの 1 つの例外は、アダプタからの入力を使用していない場合に、Python でコールバック・メソッドを実装できることです。
以下のビジネス・サービスの例は poller として知られています。この場合、ビジネス・サービスは間を置いて実行するよう設定でき、処理のためにビジネス・プロセスに送信される要求 (この場合はランダムな文字列値を含む) を生成します。この例では、OnProcessInput() コールバック・メソッドを Python に実装できます。これはこのメソッドのシグニチャで pInput 引数を利用していないためです。
Class Debug.Service.Poller Extends Ens.BusinessService
{
Property Target As Ens.DataType.ConfigName;
Parameter SETTINGS = "Target:Basic";
Parameter ADAPTER = "Ens.InboundAdapter";
Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject,
ByRef pHint As %String) As %Status [ Language = python ]
{
import iris
import random
fruits = ["apple", "banana", "cherry"]
fruit = random.choice(fruits)
request = iris.cls('Ens.StringRequest')._New()
request.StringValue = fruit + ' ' + iris.cls('Debug.Service.Poller').GetSomeText()
return self.SendRequestAsync(self.Target,request)
}
ClassMethod GetSomeText() As %String
{
Quit "is something to eat"
}
}
相互運用プロダクションのプログラミングに関する詳細は、"ビジネス・サービス、ビジネス・プロセス、およびビジネス・オペレーションのプログラミング" を参照してください。