[rbatchgenerator#6] Difference between TInterpreter::LoadMacro() and TInterpreter::LoadFile()?


ROOT Version: 6.38.04 ( tags/v6-38-04@v6-38-04)
Platform: linuxx8664gcc
Compiler: c++ (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 std201703


Hello,

TL;DR I wasn’t able to get error code of gInterpreter.LoadMacro() in Python. So I switched to gInterpreter.LoadFile().

C++: LoadMacro(): OK

With Cling, fetching error code of gInterpreter->LoadMacro() seems to work, e.g. with a non-existing file:

15:56 $ date
mar. 02 juin 2026 15:56:54 CEST
(torch) ✔ /.../rbatchgenerator [6-vector-of-vector|…2] 
15:56 $ root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.38.04                        https://root.cern |
  | (c) 1995-2025, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Apr 27 2026, 12:34:46                 |
  | From tags/v6-38-04@v6-38-04                                      |
  | With c++ (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 std201703       |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

root [0] TInterpreter::EErrorCode error
(TInterpreter::EErrorCode) (TInterpreter::kNoError) : (unsigned int) 0
root [1] gInterpreter->LoadMacro("non-existing", &error)
root [2] error
(TInterpreter::EErrorCode) (TInterpreter::kRecoverable) : (unsigned int) 1
root [3] .q

Python: LoadMacro(): KO?

However, I wasn’t able to get the same result in Python:

15:58 $ python
Python 3.12.3 (main, Mar 23 2026, 19:04:32) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ROOT
>>> error = ROOT.TInterpreter.EErrorCode()
>>> error
(TInterpreter::EErrorCode::TInterpreter::EErrorCode) : (unsigned int) 0
>>> ROOT.gInterpreter.LoadMacro("non-existing", error)
>>> error
(TInterpreter::EErrorCode::TInterpreter::EErrorCode) : (unsigned int) 0
>>> exit()

Documentation I found but don’t fully understand:

Python: LoadFile(): OK

As an alternative, gInterpreter.LoadFile() seems to work with Python:

16:12 $ python
Python 3.12.3 (main, Mar 23 2026, 19:04:32) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ROOT
>>> ROOT.gInterpreter.LoadFile("non-existing")
1
>>> exit()

Documentation I found but don’t fully understand:

Discussion

  • Could you explain in simple terms the difference between LoadMacro() and LoadFile()?
  • In Python, how can I fetch error with LoadMacro()?

Best regards,

Hello,

Sorry for answering now, but we wanted to discuss the matter internally.
Your workaround is good, internally the two methods basically do the same thing, except providing a little less granularity in the error type returned. Why two of them? This is for historical reasons, rooted in the ROOT5 to ROOT6 transition. In some sense, your observation is another reminder for the ROOT Project about the need felt for a modernisation of interfaces, which is ongoing, see e.g. the “R” components (RFile, RHist, RDataFrame, RNTuple…), but did not expand yet to Core components.

About the usability from Python, the root cause is the fact that the enum has an integer for storage type, and that, in Python, is a Python integer. That signature could be Pythonised, in order to recover the behaviour in C++, but, given the alternative, perhaps that work cannot have high priority.

I hope the above makes sense.

Thanks again for the smart post!

Danilo