Hi all.
I'm using the inspect module to extract information about our code. The code runs well in the Python console but when called from Universe Basic I'm getting a Python runtime error.
The Python side is really simple. I've reduced my code to a minimal example that reproduces it:
File: leer_documentacion_min.py
This is the module that does the inspection
import inspect
import json
import sys
def parameter_as_string(name, p):
def_value = f' = {p.default}' if (not type(p.default) == type(inspect._empty)) else ''
typ_annot = f':{p.annotation.__name__}' if (p.annotation.__name__ != '_empty') else ''
return f'{name}{typ_annot}{def_value}'
def leer_documentacion_y_funciones(script):
try:
if script in sys.modules:
sys.modules.pop(script)
modulo = __import__(script)
# rest of the code
documentacion = modulo.__doc__ if modulo.__doc__ else 'Sin documentacion.'
funciones = inspect.getmembers(modulo, inspect.isfunction)
informacion_funciones = []
for nombre, funcion_py in funciones:
argumentos = inspect.signature(funcion_py).parameters
lista_args = [parameter_as_string(p, argumentos[p]) for p in argumentos]
informacion_funciones.append({'nombre': nombre, 'argumentos': '|'.join(lista_args)})
sys.modules.pop(script)
return json.dumps({
'documentacion': documentacion,
'numero_de_funciones': len(funciones),
'informacion_funciones': informacion_funciones
})
except Exception as e:
print(inspect.stack())
import traceback
traceback.print_exc()
return f'KO - {e}'
File: lanza_metodo_min.py
This code is -mostly- irrelevant, as the part that reproduces the error is the first import.
import requests
import json
def lanza_metodo(client_id: str, client_secret: str, code: str, api: str, version: int, tipo_http: str, metodo: str):
salida = False
try:
response_get = requests.get('https://community.rocketsoftware.com/home')
salida = req.status_code == requests.codes.ok
except Exception as err:
print('Se ha producido un error general en la peticion ' + tipo_http + ' /' + metodo + ': ' + str(err))
return salida
Now I write a simple BASIC UP:
RESPUESTA=PyCallFunction('leer_documentacion_min','leer_documentacion_y_funciones','lanza_metodo_min')
CRT 'Respuesta 1: ':RESPUESTA
When I run the code from the Python terminal it works fine, as expected:
SH-4.4$ /uv/python/bin/python3
Python 3.11.0 (main, Nov 16 2022, 04:47:09) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import leer_documentacion_min
>>> leer_documentacion_min.leer_documentacion_y_funciones('lanza_metodo_min')
'{"documentacion": "...", "numero_de_funciones": 1, "informacion_funciones": [{"nombre": "lanza_metodo", "argumentos": "client_id:str|client_secret:str|code:str|api:str|version:int|tipo_http:str|metodo:str"}]}'
>>> leer_documentacion_min.leer_documentacion_y_funciones('lanza_metodo_min')
'{"documentacion": "...", "numero_de_funciones": 1, "informacion_funciones": [{"nombre": "lanza_metodo", "argumentos": "client_id:str|client_secret:str|code:str|api:str|version:int|tipo_http:str|metodo:str"}]}'
>>> leer_documentacion_min.leer_documentacion_y_funciones('lanza_metodo_min')
'{"documentacion": "...", "numero_de_funciones": 1, "informacion_funciones": [{"nombre": "lanza_metodo", "argumentos": "client_id:str|client_secret:str|code:str|api:str|version:int|tipo_http:str|metodo:str"}]}'
>>>
But when I run the BASIC UP from the TCL it starts to throw exceptions after the first call:
>RUN UP HCH_CRL
Respuesta 1: {"documentacion": "...", "numero_de_funciones": 1, "informacion_funciones": [{"nombre": "lanza_metodo", "argumentos": "client_id:str|client_secret:str|code:str|api:str|version:int|tipo_http:str|metodo:str"}]}
>.X
01 RUN UP HCH_CRL
[FrameInfo(frame=<frame at 0x7f3518462440, file '/u2/quiter/GEN4GL/PYPROGS/leer_documentacion_min.py', line 36, code leer_documentacion_y_funciones>, filename='/u2/quiter/GEN4GL/PYPROGS/leer_documentacion_min.py', lineno=36, function='leer_documentacion_y_funciones', code_context=[' print(inspect.stack())\\n'], index=0, positions=Positions(lineno=36, end_lineno=36, col_offset=14, end_col_offset=29))]
Traceback (most recent call last):
File "/u2/quiter/GEN4GL/PYPROGS/leer_documentacion_min.py", line 19, in leer_documentacion_y_funciones
modulo = __import__(script)
^^^^^^^^^^^^^^^^^^
File "/u2/quiter/GEN4GL/PYPROGS/lanza_metodo_min.py", line 7, in <module>
import requests
File "/usr/uv/python/lib/python3.11/site-packages/requests/__init__.py", line 48, in <module>
from charset_normalizer import __version__ as charset_normalizer_version
File "/usr/uv/python/lib/python3.11/site-packages/charset_normalizer/__init__.py", line 24, in <module>
from .api import from_bytes, from_fp, from_path, is_binary
File "/usr/uv/python/lib/python3.11/site-packages/charset_normalizer/api.py", line 5, in <module>
from .cd import (
File "/usr/uv/python/lib/python3.11/site-packages/charset_normalizer/cd.py", line 14, in <module>
from .md import is_suspiciously_successive_range
SystemError: initialization of md__mypyc did not return an extension module
Respuesta 1: KO - initialization of md__mypyc did not return an extension module
>
Why am I having this different behavior from the BASIC PyCallFunction?
How can I fix this issue?
------------------------------
Héctor Cortiguera
Quiter Servicios Informaticos SL
------------------------------