TPython problem

I am trying to evaluate a simple python expression:

TString python = TPython::Eval("import sys;'python%d.%d'%(sys.version_info.major,sys.version_info.minor)")

Could you, please, tell me how to do it.

This works for me, maybe it can give some inspiration:

root [0] TPython::Exec("import sys")
root [1] auto ret = TPython::Eval("'python%d.%d'%(sys.version_info.major,sys.version_info.minor)")
root [2] (const char*)ret
(const char *) "python3.7"

I tried that, too (before posting the question).

This is Ubuntu 20.04 / x86_64, gcc 9.3.0, Python 3.8.10, ROOT 6.24/02 (your “binary distribution”).

root [0] TPython::Exec("import sys")
(bool) true
root [1] auto ret = TPython::Eval("'python%d.%d'%(sys.version_info.major,sys.version_info.minor)")
input_line_29:74:12: error: expected member name or ';' after declaration specifiers
 TPyReturn isascii() {
 ~~~~~~~~~ ^
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
                        ^
/usr/include/ctype.h:99:26: note: expanded from macro '__isascii'
#define __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
                            ^
input_line_29:74:12: error: expected ')'
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
                        ^
/usr/include/ctype.h:99:28: note: expanded from macro '__isascii'
#define __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
                              ^
input_line_29:74:12: note: to match this '('
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
                        ^
/usr/include/ctype.h:99:23: note: expanded from macro '__isascii'
#define __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
                         ^
input_line_29:74:12: error: expected ')'
 TPyReturn isascii() {
           ^
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
                        ^
/usr/include/ctype.h:99:37: note: expanded from macro '__isascii'
#define __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
                                       ^
input_line_29:74:12: note: to match this '('
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
                        ^
/usr/include/ctype.h:99:22: note: expanded from macro '__isascii'
#define __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit value.  */
                        ^
(TPyReturn &) @0x7f7b1c178010
root [2] .q

Err okay that looks - somewhere between scary and weird? No need to mention that, I guess - but: 'works for me" :slight_smile:

Now, where’s that isascii coming from? Does it fail the same with

TPython::("import sys")
auto ret = TPython::Eval("42")

?

root [0] TPython::Exec("import sys")
(bool) true
root [1] auto ret = TPython::Eval("42")
(TPyReturn &) @0x7fbeb01fc010
root [2] (int)ret
(int) 42

Well okay, next step:

TPython::Exec("import sys")
auto ret = TPython::Eval("sys.version_info.major")

And then

TPython::Exec("import sys")
auto ret = TPython::Eval("'foo%d'%(42)")

The first works fine, the second generated the “TPyReturn isascii()” problem.

The simplest thing that crashes is (no need to “import sys”):

root [0] TPython::Eval("'42'")
input_line_28:74:12: error: expected member name or ';' after declaration specifiers
 TPyReturn isascii() {
 ~~~~~~~~~ ^
/usr/include/ctype.h:225:22: note: expanded from macro 'isascii'
#  define isascii(c)    __isascii (c)
...

I’ll need to debug, that doesn’t seem to be triggered immediately from our code.

A workaround is this obviously returning sys.version_info.major and sys.version_info.minor by number…

Yes, this works:
TString::Format("python%d.%d", (int)TPython::Eval("sys.version_info.major"), (int)TPython::Eval("sys.version_info.minor"))

But I somehow hesitate to advertise the usage of “TPython” when basic things are broken.

Actually, maybe you know some “builtin” way to get this magic string (e.g., “python2.7” or “python3.8”) from ROOT?

As I said, I need to debug - I don’t know where this is coming from. But I can reproduce it now!

What works is good old C/C++:

root [0] &TPython::Eval; // trigger loading of python
root [1] extern "C" const char* Py_GetVersion();
root [2] Py_GetVersion()
(const char *) "3.8.10 (default..."

OK I understand where the error with isascii is coming from but I don’t know yet how to solve it. I’m waiting for @etejedor to be back next week and will discuss with him. (And yes we need a test.)

But you should have a trivial workaround now :slight_smile:

Thanks.

I was hoping you knew some trivial way to get the “PYTHON_VERSION_MAJOR” and the “PYTHON_VERSION_MINOR” (e.g., as returned among the “gROOT->GetConfigOptions()” output).

The simplest, that I could find, is (ROOT 6 only):

TString python(gROOT->GetConfigOptions());
if (!TPRegexp(".*PYTHON_VERSION_MAJOR=([0-9]*).+PYTHON_VERSION_MINOR=([0-9]*).*").Substitute(python, "python$1.$2")) python = "python";
std::cout << python << std::endl;

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