新しい投稿

查找

記事
· 2026年2月5日 3m read

Using Python Audit for Embedded Python debugging

PEP 578 added Python Audit hooks. A rich variety of events (module load, os interactions and so on) triggers audit events which you can subscribe to.

Here's how to do that. First create an embedded python hook:

Class User.Python
{

/// do ##class(User.Python).Audit()
ClassMethod Audit() [ Language = python ]
{
import sys
import time
def logger(event,args):
     if event=='import':
        module = args[0]
        print(f"Loading {module}")
        if module == "numpy":
            print(f"Module {module} forbidden. Terminating process in 3.")
            time.sleep(3)
            sys.exit(0)
     elif event in ('compile','exec'):
        print(f"{event}: {args}")
     elif event in ('code.__new__','open'):
        # do nothing for this event
        x=1
     else:
        print(f"{event}")

sys.addaudithook(logger)
}

}

In this example we:

  • Terminate the process if numpy starts loading
  • Output event and arguments for compile/exec events
  • Ignore code events
  • Log all other events

All of that will be written to the default STDOUT.

To start auditing it's enough to call this method to register your hook, or you can even do it automatically on job start:

%ZSTART
JOB
    new $namespace
    set $namespace = "%SYS"
    do ##class(User.Python).Audit()
    quit

LOGIN
    do JOB
    quit

Here's a sample output:

%SYS>:PY
Loading code
exec: (<code object <module> at 0x000001AB82A0F2F0, file "c:\intersystems\iris\lib\python\lib\code.py", line 1>,)
Loading traceback
exec: (<code object <module> at 0x000001AB82A173A0, file "c:\intersystems\iris\lib\python\lib\traceback.py", line 1>,)
Loading linecache
exec: (<code object <module> at 0x000001AB82A17A80, file "c:\intersystems\iris\lib\python\lib\linecache.py", line 1>,)
Loading tokenize
exec: (<code object <module> at 0x000001AB82A32030, file "c:\intersystems\iris\lib\python\lib\tokenize.py", line 1>,)
Loading token
exec: (<code object <module> at 0x000001AB82A323A0, file "c:\intersystems\iris\lib\python\lib\token.py", line 1>,)
compile: (b'lambda _cls, type, string, start, end, line: _tuple_new(_cls, (type, string, start, end, line))', '<string>')
exec: (<code object <module> at 0x000001AB82A32710, file "<string>", line 1>,)
sys._getframe
object.__setattr__
Loading codeop
exec: (<code object <module> at 0x000001AB82A32EA0, file "c:\intersystems\iris\lib\python\lib\codeop.py", line 1>,)
Loading __future__
exec: (<code object <module> at 0x000001AB82A472F0, file "c:\intersystems\iris\lib\python\lib\__future__.py", line 1>,)
 
Python 3.9.5 (default, May 31 2022, 12:35:47) [MSC v.1927 64 bit (AMD64)] on win32
Type quit() or Ctrl-D to exit this shell.
compile: (b'import iris', '<input>')
compile: (b'import iris\n', '<input>')
compile: (b'import iris\n\n', '<input>')
exec: (<code object <module> at 0x000001AB82A60870, file "<input>", line 1>,)
>>> import json
compile: (b'import json', '<input>')
compile: (b'import json\n', '<input>')
compile: (b'import json\n\n', '<input>')
exec: (<code object <module> at 0x000001AB82A60870, file "<input>", line 1>,)
Loading json
exec: (<code object <module> at 0x000001AB82A60DF0, file "c:\intersystems\iris\lib\python\lib\json\__init__.py", line 1>,)
Loading json.decoder
os.listdir
exec: (<code object <module> at 0x000001AB82A67710, file "c:\intersystems\iris\lib\python\lib\json\decoder.py", line 1>,)
Loading json.scanner
exec: (<code object <module> at 0x000001AB82A679D0, file "c:\intersystems\iris\lib\python\lib\json\scanner.py", line 1>,)
Loading _json
Loading json.encoder
exec: (<code object <module> at 0x000001AB82A71500, file "c:\intersystems\iris\lib\python\lib\json\encoder.py", line 1>,)
>>> x=1
compile: (b'x=1', '<input>')
compile: (b'x=1\n', '<input>')
compile: (b'x=1\n\n', '<input>')
exec: (<code object <module> at 0x000001AB82A60870, file "<input>", line 1>,)

I find it can be helpful for debugging.

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2026年2月5日

JSON Response Help - Extracting Data into Data Class or Iteration to Extract Data

I have always struggled with Iterating through a JSON response to pull out certain fields into a Data Class Structure to use to populate fields in a DTL. So I defined the whole structure for the following JSON, with the base structure extending Ens.Response, %XML.Adaptor, and %JSON.Adaptor.

{
    "status": {
        "message": "success",
        "code": 200
    },
    "data": {
        "client": "xxxxxxxxxxxxxxxxxxxxxxxx",
        "entities": [
            {
                "id": "xxxxxxxxxxxxxxxxxx`",
                "name": "xxxxxxxxxxxxxxxxx",
                "totalCommentCount": 272,
                "totalRatingCount": 396,
                "totalSurveyCount": 396,
                "overallRating": {
                    "name": "Overall Satisfaction",
                    "value": 4.9,
                    "categoryResponseCount": 396,
                    "questionRatings": [
                        {
                            "name": "Provider listen carefully to you",
                            "value": 5.0,
                            "responseCount": 395
                        },
                        {
                            "name": "Provider expl in way you understand",
                            "value": 5.0,
                            "responseCount": 396
                        },
                        {
                            "name": "Talk with provider re prob/concern",
                            "value": 4.5,
                            "responseCount": 394
                        },
                        {
                            "name": "Know important info medical history",
                            "value": 4.9,
                            "responseCount": 393
                        },
                        {
                            "name": "Give easy to understand instruction",
                            "value": 4.9,
                            "responseCount": 347
                        },
                        {
                            "name": "Spend enough time with you",
                            "value": 4.9,
                            "responseCount": 395
                        },
                        {
                            "name": "Show respect for what you say",
                            "value": 5.0,
                            "responseCount": 395
                        }
                    ]
                },
                "comments": [],
                "PGSealOfIntegrity": {
                    "dataIntegrity": {
                        "horizontal": {
                            "darkBackground": {
                                "png": "xxxxxx"
                            },
                            "lightBackground": {
                                "jpg": "xxxxxxxxxxxxxxxxx",
                                "png": "xxxxxxxxxxxxxxxx"
                            },
                            "darkBackgroundHighResolution": {
                                "png": "xxxxxxxxxxxxxx"
                            }
                        },
                        "stacked": {
                            "darkBackground": {
                                "png": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"x
                            },
                            "lightBackground": {
                                "jpg": "xxxxxxxxxxxxxxxxx",
                                "png": "XXXXXXXXXXXXXXX"
                            }
                        }
                    },
                    "sealOfIntegrity": {
                        "darkBackground": {
                            "jpg": "XXXXXXXXXXXXXXXXXXXXXXXX",
                            "png": "XXXXXXXXXXXXXXXXXXXXXXXX"
                        },
                        "lightBackground": {
                            "jpg": "XXXXXXXXXXXXXXXXXXXXXXXXXX",
                            "png": "XXXXXXXXXXXXXXXXXXXXXXXXXX"
                        }
                    }
                },
                "totalPages": 14,
                "ratings": []
            }
        ],
        "filter": {
            "minThreshold": 0.0,
            "minRatingCount": 30,
            "minSurveyCount": 0,
            "minWordCount": 0,
            "days": 365,
            "page": 1,
            "perPage": 20,
            "showComments": false,
            "showRatings": true,
            "configVersion": "v2",
            "period": {
                "to": "2026-02-05T23:59:59Z",
                "from": "2025-02-05T00:00:00Z"
            }
        }
    }
}

The rest of the structure that is referenced by the base Response.cls structure extends %RegisteredObject, %JSON.Adaptor.

I am able to make the REST call, and the Response is populating into the Response.cls, however within the Trace Viewer the Response is blank. I know the data is there because when I send it to a DTL, I can pull the data elements out.

How do I make the Response show up within the Trace Viewer, or how would I go about extracting the values in RED below

                "id": "xxxxxx",

                "name": "xxxxxx",

                "totalCommentCount": 272,

                "totalRatingCount": 396,

                "totalSurveyCount": 396,

                "overallRating": {

                    "name": "Overall Satisfaction",

                    "value": 4.9,

5件の新着コメント
ディスカッション (5)4
続けるにはログインするか新規登録を行ってください
質問
· 2026年2月5日

Splitting stream into HL7 messages

Hi,

I want to consume an API that provides HL7 messages. To achieve this, I have thought of the following workflow:

I have created a business service that periodically triggers a business process. The trigger request is forwarded to a business operation. There, a %Net.HttpRequest is assembled from scratch and then sent to the API endpoint. The corresponding HttpResponse then contains several HL7 messages encoded in UTF-8 in the message body. To further process the HL7 messages, the operation sends the HttpResponse back to the business process as EnsLib.HTTP.GenericMessage.

The raw data looks like this:

MSH|^~\&|Doctolib||Doctolib||20251028154100||SIU^S12|d50f01e649cda79faf29|P|2.5.1|||||FRA|UTF-8
SCH||20771389^Doctolib||||Vor.Tagesk^Vorgespräch für Tagesklinik|||||^^15^202511101000|||||117134^Mustermann^Stefan||||Doctolib|||||Booked
NTE|||Hier der Inhalt des Notizfeldes.  Achten Sie auf Umlaute: ä ö ü   (UTF-8)
PID|||56834111^^^Doctolib^PI||Testfrau^Liselotte^^^^^L||19690722|F|||||+4917612345678^^^liselotte@test.de~+4940123456
RGS|1
AIG|1|||Vorg-Tagesklinik^Vorgespräche Tagesklinik
MSH|^~\&|Doctolib||Doctolib||20251028154114||SIU^S13|39e482e10fa61ccd4500|P|2.5.1|||||FRA|UTF-8
SCH||20771389^Doctolib||||Vor.Tagesk^Vorgespräch für Tagesklinik|||||^^15^202511141600|||||117134^Mustermann^Stefan||||Doctolib|||||Booked
NTE|||Hier der Inhalt des Notizfeldes.  Achten Sie auf Umlaute: ä ö ü   (UTF-8)
PID|||56834111^^^Doctolib^PI||Testfrau^Liselotte^^^^^L||19690722|F|||||+4917612345678^^^liselotte@test.de~+4940123456
RGS|1
AIG|1|||Vorg-Tagesklinik^Vorgespräche Tagesklinik
MSH|^~\&|Doctolib||Doctolib||20251028154225||SIU^S17|1e5726345c7b4257b41f|P|2.5.1|||||FRA|UTF-8
SCH||20771388^Doctolib||||Vor.Tagesk^Vorgespräch für Tagesklinik|||||^^15^202511121600|||||117134^Mustermann^Stefan||||Doctolib|||||Deleted
NTE|||Hier der Inhalt des Notizfeldes
PID|||56834102^^^Doctolib^PI||Testmann^Heinrich^^^^^L||19881211|M|||||+4917612345678^^^heinrich@test.de~+4940123456
RGS|1
AIG|1|||Vorg-Tagesklinik^Vorgespräche Tagesklinik

 

The next step would be to split the message body into individual HL7 messages and then forward them accordingly. But splitting them up is causing me problems. In the message viewer, the stream is still displayed with line breaks. First, I tried to read the stream line by line and then save the individual streams in a collection (%ListOfObjects). However, the line breaks seem to get lost in the process.

Then I tried to save it in a collection of strings using the string “MSH|” (the start of the message) to split the stream. That worked, but unfortunately there were problems when converting the string to an EnsLib.HL7.Message because the framing did not fit.

How would you go about turning a stream with multiple HL7 messages into individual HL7 messages?

Regards

Robert

3件の新着コメント
ディスカッション (3)3
続けるにはログインするか新規登録を行ってください
Job
· 2026年2月5日

Intersystems Cache & Iris Developer - Object Script. Remote (UK company)

Developer required to join a team working with and extending an existing CACHE application and subsequent migration to IRIS.

4yrs Minimum experience.

Applicants must have good general knowledge of development approaches and patterns.

SQL 

Opportunity from 6 Month contract to Permanent, depending on experience. Immediate start

Applications to chris.clipston@mtivity.com

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2026年2月5日 14m read

Présentation des fonctions de fenêtre SQL (3ème partie)

Dans cette dernière partie de notre présentation des fonctions de fenêtre, nous allons explorer les fonctions restantes qui n'ont pas encore été abordées. Vous découvrirez également des conseils de performance et un guide pratique pour vous aider à décider quand il convient (ou non) d'utiliser efficacement les fonctions de fenêtre.

ディスカッション (0)2
続けるにはログインするか新規登録を行ってください