1

I'm using BoostPython for embedding Python in my C++ project but I don't understand all stuffs about Python, especially the namespace system.

Actually, I used this code:

byte_code = Py_CompileString(filedata, filename, Py_file_input);

// [...]

PyObject* res = NULL;

PyObject* main_module = PyImport_AddModule("__main__");
PyObject* global_dict = PyModule_GetDict(main_module);
PyObject* local_dict = PyDict_New();
py::object local_namespace(py::handle<>(py::borrowed(local_dict)));

// Set a user object (only for this execution)
local_namespace["user_object"] = py::ptr(&MyObject);

res = PyEval_EvalCode( byte_code, global_dict, local_dict );

Py_XDECREF(res);
Py_XDECREF(local_dict);

But When I execute a python script like:

def testB():
    print("B")

def testA():
    testB() # NameError: global name 'testB' is not defined

testA() # Works
testB() # Works

Okay I could used

res = PyEval_EvalCode( byte_code, global_dict, global_dict );

instead of

res = PyEval_EvalCode( byte_code, global_dict, local_dict );

But I want preserve the global_dict from any new function definition (Because when I will launch a new script, I don't want that previous function definition from a very old execution can be called !)

This is a problem about namespace, isn't it ?

Deanie
  • 2,316
  • 2
  • 19
  • 35
yoder
  • 63
  • 2
  • 5

1 Answers1

0

Yes, this is a namespace problem. You should look into the way Python handles scope (specifically the "self" keyword).

In short, class member variables and functions are prefixed with "self." in order to specify that they are a member of the current object's scope. "Self" is loosely similar to the "this" keyword in C++ and C#.

Matt
  • 775
  • 7
  • 24
  • thank you for your answer. I tried "self.testB()" but it doesn't work... (NameError: global name 'self' is not defined) I suppose that isn't a python class. Mmmh or maybe I must delete all contents from global_dict to clean it... – yoder Nov 05 '13 at 00:20
  • ... Maybe I found a better solution ! I used "PyDict_Copy" to copy the global_dict. Then I send the copy for "PyEval_EvalCode( byte_code, copy_dict, copy_dict )". After this, I can trash this copy to preserve the real global_dict ! – yoder Nov 05 '13 at 00:49
  • I didn't expect just adding "self." to work. Please do your homework. If you understand what the "self" keyword means and does, this will make sense. While your solution might "work," it is hardly better unless you understand how it's different from the other solution. Scope resolution is a very basic Python concept and you should understand how it works before you try to work around it. Don't be discouraged, your initial instinct was correct, this is a namespace problem. Understanding the way Python handles scope and namespace will solve your problem better than a work-around. – Matt Nov 05 '13 at 21:07
  • You right. In fact, that's why I didn't close this question and answer it with this work-around. I tried to find information about scope and namespace. (eg: http://docs.python.org/3.3/tutorial/classes.html#python-scopes-and-namespaces ) I think I understand well this mecanism now. However, I couldn't find a solution for my problem with these new informations... Maybe it's impossible because with the initial configuration, all function definitions are registered in local_dict (so in a local scope of the __main__ scope) which are inaccessible to the other sub scopes. (But I'm not sure... :s) – yoder Nov 07 '13 at 11:36
  • Hi, did you ever find a solution to this problem? I am having the same problem. I'm considering to use the global dict as the local dict, but the problem with that is if any objects declared global will live (eg, the destructor wont be called) until (eg not destroyed) unless they are written over. – Rickard Jan 11 '16 at 07:52
  • See also http://stackoverflow.com/questions/12265756/c-python-running-python-code-within-a-context – pi3 Jul 25 '16 at 12:10