How to pass parameters to THttpServer using python?

I am using root.js and querying a TH2I via JavaScript.
According to the THttpServer documentation am doing in Python:

import ROOT

def do_something():
    print("do something")

class Th2Maker():
    def do_something(self):

    def __init__(self):
       self.__serv = ROOT.THttpServer("http:8080")
       self.__histo = ROOT.TH2I('h1', '', 
                                self.__X_BIN_MAX, 0, self.__X_BIN_MAX,
                                self.__Y_BIN_MAX, 0, self.__Y_BIN_MAX)
       for x in range(0, self.__X_BIN_MAX):
           for y in range(0, self.__Y_BIN_MAX):
               self.__histo.SetBinContent(x, y, x+y)
       self.__serv.Register("subfolder", self.__histo)
       self.__serv.RegisterCommand('/Folder/Start', 'do_something()')
       self.__serv.RegisterCommand('/Folder/Start2', 'self.do_something()')

    __X_BIN_MAX: Final = 200
    __Y_BIN_MAX: Final = 200 

Calling wget .../Folder/Start(2)/cmd.json -O result.txt results in

use of undeclared identifier 'do_something'

What is the Python version of passing functions to RegisterCommand()?

Welcome to the ROOT Forum!
I might be wrong, but I think do_something() must be known by the interpreter, and then declared in it. Something like:

   gInterpreter->Declare("void do_something();");

or even

   gInterpreter->Declare("void do_something() { printf(\"do something\"); }");

But maybe @etejedor knows a better way

Thanks a lot for the very fast replay.

That might be the C++ way. But I need Python.


does not work there.

ROOT.gInterpreter.Declare("void do_something(){std::cout << \"jjjjj\" << std::endl;}");

works - but I need to access the rest of my Python code in the function.

So @etejedor, our PyROOT expert can help you with that

If do_something is a free function in Python, you can do:

self.__serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something()")')

self.do_something won’t work because TPython will run the code you pass in the global scope of Python. What you could do is create a o = Th2Maker() object in the global scope and do o.do_something() in TPython.

Basic version (without parameters and class):

import signal
import threading

import ROOT

def do_something():
     print("do something")

serv = ROOT.THttpServer("http:8080")
serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something()")')

def keep_alive():

x = threading.Thread(target=keep_alive)

wget http://localhost:8080/Folder/Start/cmd.json -O result.txt → result:

Info in <THttpEngine::Create>: Starting HTTP server on port 8080
 *** Break *** segmentation violation
The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
#7  0x000000000055165c in PyImport_GetModuleDict ()
#8  0x0000000000683c9e in PyImport_AddModule ()
#9  0x00007f4e0855f1bc in TPython::Initialize() () from /home/jens/bin/root/lib/
#10 0x00007f4e0855f813 in TPython::Exec(char const*) () from /home/jens/bin/root/lib/
#11 0x00007f4e1273103e in ?? ()
#12 0x00007f4dfcff80a0 in ?? ()
#13 0x000000000379dce0 in ?? ()
#14 0x000000000379dce0 in ?? ()
#15 0x00007f4dfcff8490 in ?? ()
#16 0x0000000002059c90 in ?? ()
#17 0x00007f4dfcff8490 in ?? ()
#18 0x0000000003952a30 in ?? ()
#19 0x00007f4e1677e924 in cling::IncrementalExecutor::executeWrapper(llvm::StringRef, cling::Value*) const () from /home/jens/bin/root/lib/
#20 0x00007f4e16706767 in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) () from /home/jens/bin/root/lib/
#21 0x00007f4e1670806d in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /home/jens/bin/root/lib/
#22 0x00007f4e16708389 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /home/jens/bin/root/lib/
#23 0x00007f4e167d151d in cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /home/jens/bin/root/lib/
#24 0x00007f4e1665c39c in HandleInterpreterException(cling::MetaProcessor*, char const*, cling::Interpreter::CompilationResult&, cling::Value*) () from /home/jens/bin/root/lib/

Another option could be that RegisterCommand implements an overload that accepts an std::function, since those are directly convertible from a Python callable, but I think that’s not the case now @bellenot?

On the other hand, the example works if you don’t spawn a server thread:

import signal
import threading

import ROOT

def do_something():
     print("do something")

serv = ROOT.THttpServer("http:8080")
serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something()")')

def keep_alive():

x = threading.Thread(target=keep_alive)

Thanks a lot - It seems that I forgot to remove it or never test without it after inserting the threading / signal to run the program forever without blocking the THttpServer.

One last question: What is about passing strings as parameters? %argN% seems to be an fixed topic for RegisterCommand (and it is not for http / GET). Passing integers or floats works but when passing strings I got errors:

 def do_something(arg1=None):
      print("do something", arg1)

serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something(%arg1%)")')
wget http://localhost:8080/Folder/Start/cmd.json?arg1=rr -O result.txt
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'rr' is not defined

The intent is to pass a filename for data input for TH2I.

No, it’s not the case…


I think you need to do (notice the quotes around %arg1):

serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something(\"%arg1%\")")')

So you need to make sure the function receives a string literal "rr", otherwise the arg is treated as a variable name rr (this applies both for Python and C++).

OK - in Python single quotes are needed:

serv.RegisterCommand('/Folder/Start', 'TPython::Exec("do_something(\'%arg1%\')")')

Then passing wget http://localhost:8080/Folder/Start/cmd.json?arg1=rr -O result.txt works as expected.

Thanks a lot - for my part the issue can be closed.

It is different when running inside a docker container. Without serv.CreateServerThread() the process is halted and not processing any requests. Unfortunality with self.__serv.CreateServerThread() it crashes when receiving the request set via RegisterCommand while a request for a histogram (set via self.__serv.Register("subfolder", self.__histo) works.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.