Hi JonB and ccc, thanks for your post, two days ago I didn't know anything about json, now I know what it is but I can't work/play with it, sorry, I will study further. For now I have a working script that convert the full output into a array or matrix for numpy ( also scalars).
"""
A small client illustrating how to interact with the Sage Cell Server, version 2
Requires the websocket-client package: http://pypi.python.org/pypi/websocket-client
"""
import websocket
import json
import requests
import numpy as np
import re
class SageCell(object):
def __init__(self, url, timeout=10):
if not url.endswith('/'):
url += '/'
# POST or GET <url>/kernel
# if there is a terms of service agreement, you need to
# indicate acceptance in the data parameter below (see the API docs)
response = requests.post(
url + 'kernel',
data={'accepted_tos': 'true'},
headers={'Accept': 'application/json'}).json()
# RESPONSE: {"id": "ce20fada-f757-45e5-92fa-05e952dd9c87", "ws_url": "ws://localhost:8888/"}
# construct the websocket channel url from that
self.kernel_url = '{ws_url}kernel/{id}/'.format(**response)
print self.kernel_url
websocket.setdefaulttimeout(timeout)
self._ws = websocket.create_connection(
self.kernel_url + 'channels',
header={'Jupyter-Kernel-ID': response['id']})
# initialize our list of messages
self.shell_messages = []
self.iopub_messages = []
def execute_request(self, code):
# zero out our list of messages, in case this is not the first request
self.shell_messages = []
self.iopub_messages = []
# Send the JSON execute_request message string down the shell channel
msg = self._make_execute_request(code)
self._ws.send(msg)
# Wait until we get both a kernel status idle message and an execute_reply message
got_execute_reply = False
got_idle_status = False
while not (got_execute_reply and got_idle_status):
msg = json.loads(self._ws.recv())
if msg['channel'] == 'shell':
self.shell_messages.append(msg)
# an execute_reply message signifies the computation is done
if msg['header']['msg_type'] == 'execute_reply':
got_execute_reply = True
elif msg['channel'] == 'iopub':
self.iopub_messages.append(msg)
# the kernel status idle message signifies the kernel is done
if (msg['header']['msg_type'] == 'status' and
msg['content']['execution_state'] == 'idle'):
got_idle_status = True
return {'shell': self.shell_messages, 'iopub': self.iopub_messages}
def _make_execute_request(self, code):
from uuid import uuid4
session = str(uuid4())
# Here is the general form for an execute_request message
execute_request = {
'channel': 'shell',
'header': {
'msg_type': 'execute_request',
'msg_id': str(uuid4()),
'username': '', 'session': session,
},
'parent_header':{},
'metadata': {},
'content': {
'code': code,
'silent': False,
'user_expressions': {
'_sagecell_files': 'sys._sage_.new_files()',
},
'allow_stdin': False,
}
}
return json.dumps(execute_request)
def close(self):
# If we define this, we can use the closing() context manager to automatically close the channels
self._ws.close()
if __name__ == "__main__":
import sys
if len(sys.argv) >= 2:
# argv[1] is the web address
url = sys.argv[1]
else:
url = 'https://sagecell.sagemath.org'
a = SageCell(url)
import pprint
###############################################
string_for_SageMathCell = """
### SageMath - ODE System Solver:
import numpy as np
# Parameters:
t_begin = 0
t_end = 5
step = 0.05
h , g = var(' h , g ')
t = var(' t ')
# ODEs and ICs:
# 'dhdt=g-t-2' et
# 'dgdt=h+g+t' with
# 'h(t=0)=1' et
# 'g(t=0)=3'
functions = [ h , g ]
indep_var = t
system = [ g-t-2 , h+g+t ]
init_conds = [ 1 , 3 ]
# Solver:
time_interval = srange(t_begin, t_end+step, step)
solution = desolve_odeint(system, init_conds, time_interval, functions, indep_var)
# Output matrix:
number_of_steps = Integer((t_end-t_begin)/step)+1
time_interval_Matrix = np.reshape(time_interval, (1, number_of_steps))
solution_t_functions = np.concatenate((time_interval_Matrix.T, solution), axis=1)
print(solution_t_functions)
"""
###############################################
#pprint.pprint(a.execute_request(string_for_SageMathCell))
#### use of regex to parse fullstring
data = a.execute_request(string_for_SageMathCell)
fulltext = str(data)
pattern = "(?<={u'text': u').*?(?=', u'name': u'stdout'})"
ls = re.findall(pattern, fulltext, re.DOTALL)
sage_output = str(ls[0])
sage_output_1 = sage_output.replace(r'\n', ',')
pattern = "(?<=\d)\s?(?=\s)"
sage_output_2 = re.sub(pattern, ',', sage_output_1)
sage_output_3 = eval(sage_output_2)
var1 = np.array(sage_output_3)
print(var1+1) # this is only to prove that var1 is ok for numpy
I've used regex, and massive stackoverflow.com surfing (without it I cant write more than 2-3 rows of code in python when I must work with strings and other python objects different from numbers and arrays).
I have some little ideas to increase the use of the script. I will write here in the next days.
Thanks for your help
Regards
Matteo