組み込み Python を使用していて、InterSystems IRIS とやり取りする必要がある場合、Python シェルから、または InterSystems IRIS クラスの Python で記述されたメソッドから、iris モジュールを使用できます。このセッションの例に従うには、ターミナル・セッションから、ObjectScript コマンド do ##class(%SYS.Python).Shell() を使用して Python シェルを開始します。
ターミナル・セッションから Python シェルを開始する場合、Python シェルはターミナルと同じコンテキスト (現在のネームスペースとユーザなど) を継承します。ローカル変数は継承されません。
クラスの操作
Python から InterSystems IRIS クラスにアクセスするには、iris モジュールを使用して、使用するクラスをインスタンス化します。これで、Python クラスとほとんど同じように、そのプロパティとメソッドにアクセスできるようになります。
Note:
Python でモジュールを使用するには、まず、以下のようにそれをインポートする必要がある場合があります。
>>> import iris
ただし、%SYS.PythonOpens in a new tab クラスの Shell() メソッドを使用した Python シェルの実行時に、iris モジュールを明示的にインポートする必要はありません。続行して、モジュールを使用してください。
以下の例では、システム・クラス %Library.FileOpens in a new tab の ManagerDirectory() メソッドを使用して、InterSystems IRIS マネージャ・ディレクトリにパスを出力します。
>>> lf = iris.cls('%Library.File')
>>> print(lf.ManagerDirectory())
C:\InterSystems\IRIS\mgr\
この例では、システム・クラス %SYSTEM.CPUOpens in a new tab の Dump() メソッドを使用して、InterSystems IRIS インスタンスを実行するサーバについての情報を表示します。
>>> cpu = iris.cls('%SYSTEM.CPU')
>>> cpu.Dump()
-- CPU Info for node MYSERVER ----------------------------------------------
Architecture: x86_64
Model: Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz
Vendor: Intel
# of threads: 4
# of cores: 2
# of chips: 1
# of threads per core: 2
# of cores per chip: 2
MT supported: 1
MT enabled: 1
MHz: 2904
------------------------------------------------------------------------------
この例では、GitHub の Samples-Data リポジトリから Sample.Company クラスを使用します。任意のネームスペースからパーセント記号 (%) で始まるクラス (%SYS.PythonOpens in a new tab や %Library.FileOpens in a new tab など) を使用して Sample.Company クラスにアクセスできますが、前述のように SAMPLES ネームスペースにいる必要があります。
Sample.Company のクラス定義は以下のとおりです。
Class Sample.Company Extends (%Persistent, %Populate, %XML.Adaptor)
{
/// The company's name.
Property Name As %String(MAXLEN = 80, POPSPEC = "Company()") [ Required ];
/// The company's mission statement.
Property Mission As %String(MAXLEN = 200, POPSPEC = "Mission()");
/// The unique Tax ID number for the company.
Property TaxID As %String [ Required ];
/// The last reported revenue for the company.
Property Revenue As %Integer;
/// The Employee objects associated with this Company.
Relationship Employees As Employee [ Cardinality = many, Inverse = Company ];
}
このクラスは %Library.PersistentOpens in a new tab (多くの場合 %PersistentOpens in a new tab と省略される) を拡張します。これは、このクラスのオブジェクトが、InterSystems IRIS データベースで永続化できることを意味します。このクラスには、Name や TaxID などのいくつかのプロパティもあります。このどちらもオブジェクトを保存するために必要です。
クラス定義に表示されませんが、永続クラスには、%New()、%Save()、%Id()、および %OpenId() といった、このクラスのオブジェクトを操作するための多数のメソッドが備わっています。ただし、パーセント記号 (%) は Python のメソッド名では許可されないため、代わりにアンダースコア (_) が使用されます。
以下のコードは、新しい Company オブジェクトを作成し、必要な Name および TaxID プロパティを設定した後、データベース内にこの会社を保存します。
>>> myCompany = iris.cls('Sample.Company')._New()
>>> myCompany.Name = 'Acme Widgets, Inc.'
>>> myCompany.TaxID = '123456789'
>>> status = myCompany._Save()
>>> print(status)
1
>>> print(myCompany._Id())
22
上記のコードは _New() メソッドを使用してクラスのインスタンスを作成し、_Save() を使用してデータベースにインスタンスを保存します。_Save() メソッドはステータス・コードを返します。この場合、1 は保存が成功したことを示します。オブジェクトを保存すると、InterSystems IRIS は、後でストレージからそのオブジェクトを取得するために使用できる一意の ID を割り当てます。_Id() メソッドはオブジェクトの ID を返します。
以下のように、クラスの _OpenId() メソッドを使用して、永続ストレージからメモリにオブジェクトを取り込み、処理します。
>>> yourCompany = iris.cls("Sample.Company")._OpenId(22)
>>> print(yourCompany.Name)
Acme Widgets, Inc.
以下のコードをクラス定義に追加すると、現在の会社の Name と TaxID を出力する Print() メソッドが作成されます。Language キーワードを python に設定すると、メソッドが Python で記述されていることがクラス・コンパイラに伝えられます。
Method Print() [ Language = python ]
{
print ('\nName: ' + self.Name + ' TaxID: ' + self.TaxID)
}
Company オブジェクトを指定すると、以下のようにその Print() メソッドを呼び出せます。
>>> yourCompany.Print()
Name: Acme Widgets, Inc. TaxID: 123456789
SQL の操作
InterSystems IRIS 内のクラスは SQL に投影されるため、クラス・メソッドの使用または直接グローバル・アクセスに加えて、クエリを使用してデータにアクセスできるようになります。iris モジュールは、Python から SQL ステートメントを実行するための 2 つの異なる方法を提供します。
以下の例は、iris.sql.exec() を使用して SQL SELECT 文を実行して、クラス名が "%Net.LDAP" で始まるすべてのクラス定義を検索し、各クラスの名前とスーパークラスをそれぞれ含む結果セットを返します。ここで、システム・クラス %Dictionary.ClassDefinitionOpens in a new tab は、同じ名前のテーブルとして SQL に投影します。
>>> rs = iris.sql.exec("SELECT Name, Super FROM %Dictionary.ClassDefinition WHERE Name %STARTSWITH '%Net.LDAP'")
以下の例は、iris.sql.prepare() を使用して SQL クエリ・オブジェクトを準備してからクエリを実行し、"%Net.LDAP" をパラメータとして渡します。
>>> stmt = iris.sql.prepare("SELECT Name, Super FROM %Dictionary.ClassDefinition WHERE Name %STARTSWITH ?")
>>> rs = stmt.execute("%Net.LDAP")
どちらの場合も以下のように結果セットを反復処理でき、出力は同じです。
>>> for idx, row in enumerate(rs):
... print(f"[{idx}]: {row}")
...
[0]: ['%Net.LDAP.Client.EditEntry', '%RegisteredObject']
[1]: ['%Net.LDAP.Client.Entries', '%RegisteredObject,%Collection.AbstractIterator']
[2]: ['%Net.LDAP.Client.Entry', '%RegisteredObject,%Collection.AbstractIterator']
[3]: ['%Net.LDAP.Client.PropList', '%RegisteredObject']
[4]: ['%Net.LDAP.Client.Search.Scope', '%Integer']
[5]: ['%Net.LDAP.Client.Session', '%RegisteredObject']
[6]: ['%Net.LDAP.Client.StringList', '%RegisteredObject']
[7]: ['%Net.LDAP.Client.ValueList', '%RegisteredObject,%Collection.AbstractIterator']
グローバルの操作
InterSystems IRIS データベースでは、すべてのデータはグローバルに格納されます。グローバルとは、永続的で (ディスクに格納されることを意味する)、多次元で (任意の数の添え字を使用できることを意味する)、スパースである (添え字が連続している必要がないことを意味する) 配列です。クラスのオブジェクトまたは行をテーブルに格納する場合、このデータは実際にはグローバルに格納されます。しかし、通常、これらにはメソッドまたは SQL を介してアクセスし、グローバルを直接操作することはありません。
クラスまたは SQL テーブルを設定せずに、グローバルに永続データを格納すると、便利な場合があります。InterSystems IRIS では、グローバルはその他の変数と同じように見えますが、名前の前にキャレット (^) を付記することによって示されます。以下の例は、現在のネームスペースのグローバル ^Workdays に平日の名前を格納します。
>>> myGref = iris.gref('^Workdays')
>>> myGref[None] = 5
>>> myGref[1] = 'Monday'
>>> myGref[2] = 'Tuesday'
>>> myGref[3] = 'Wednesday'
>>> myGref[4] = 'Thursday'
>>> myGref[5] = 'Friday'
>>> print(myGref[3])
Wednesday
コードの最初の行 myGref = iris.gref('^Workdays') は、^Workdays というグローバルへのグローバル参照 (または gref) を取得します。これは既に存在する場合も存在しない場合もあります。
2 行目の myGref[None] = 5 は、添え字なしで、平日の数を ^Workdays に格納します。
3 行目の myGref[1] = 'Monday' は、文字列 Monday を ^Workdays(1) の場所に格納します。次の 4 行は、残りの平日を ^Workdays(2) から ^Workdays(5) の場所に格納します。
最後の行 print(myGref[3]) は、gref を指定して、グローバルに格納された値にアクセスする方法を示しています。