PEP 578 añadió hooks de auditoría de Python. Una gran variedad de eventos (carga de módulos, interacciones con el sistema operativo, etc.) generan eventos de auditoría a los que podéis suscribiros.
Así es como se hace. Primero, cread un hook de Python embebido:
Class User.Python
{
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)
}
}
En este ejemplo:
- Terminamos el proceso si numpy comienza a cargarse
- Mostramos el evento y sus argumentos para los eventos de compile/exec
- Ignoramos los eventos de código
- Registramos todos los demás eventos
Todo esto se escribirá en el STDOUT por defecto.
Para empezar la auditoría, basta con llamar a este método para registrar vuestro hook, o incluso podéis hacerlo automáticamente al iniciar el proceso (job):
%ZSTART
JOB
new $namespace
set $namespace = "%SYS"
do ##class(User.Python).Audit()
quit
LOGIN
do JOB
quit
Aquí tenéis un ejemplo de salida:
%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>,)
Creo que esto os puede resultar útil para la depuración.