OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PythonEval.cc
Go to the documentation of this file.
1 /*
2  * @file opencog/cython/PythonEval.cc
3  * @author Zhenhua Cai <czhedu@gmail.com>
4  * Ramin Barati <rekino@gmail.com>
5  * Keyvan Mir Mohammad Sadeghi <keyvan@opencog.org>
6  * Curtis Faith <curtis.m.faith@gmail.com>
7  * @date 2011-09-20
8  *
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License v3 as
12  * published by the Free Software Foundation and including the exceptions
13  * at http://opencog.org/wiki/Licenses
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program; if not, write to:
22  * Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
26 #include <boost/filesystem/operations.hpp>
27 
28 #include <opencog/util/Config.h>
29 #include <opencog/util/exceptions.h>
30 #include <opencog/util/Logger.h>
31 #include <opencog/util/misc.h>
32 #include <opencog/util/oc_assert.h>
33 
34 #include <opencog/atomspace/Atom.h>
35 #include <opencog/atomspace/Link.h>
36 
37 #include "PythonEval.h"
38 
39 #include "opencog/atomspace_api.h"
40 
41 using std::string;
42 using std::vector;
43 
44 using namespace opencog;
45 
46 //#define DPRINTF printf
47 #define DPRINTF(...)
48 
50 
51 const int NO_SIGNAL_HANDLERS = 0;
52 const char* NO_FUNCTION_NAME = NULL;
53 const int SIMPLE_STRING_SUCCESS = 0;
54 const int SIMPLE_STRING_FAILURE = -1;
55 const int MISSING_FUNC_CODE = -1;
56 
57 // The Python functions can't take const flags.
58 #define NO_COMPILER_FLAGS NULL
59 
60 static bool already_initialized = false;
61 static bool initialized_outside_opencog = false;
62 std::recursive_mutex PythonEval::_mtx;
63 
64 /*
65  * @todo When can we remove the singleton instance?
66  *
67  * NOTE: The Python C API reference counting is very tricky and the
68  * API inconsistently handles PyObject* object ownership.
69  * DO NOT change the reference count calls below using Py_INCREF
70  * and the corresponding Py_DECREF until you completely understand
71  * the Python API concepts of "borrowed" and "stolen" references.
72  * Make absolutely NO assumptions about the type of reference the API
73  * will return. Instead, verify if it returns a "new" or "borrowed"
74  * reference. When you pass PyObject* objects to the API, don't assume
75  * you still need to decrement the reference count until you verify
76  * that the exact API call you are making does not "steal" the
77  * reference: SEE: https://docs.python.org/2/c-api/intro.html?highlight=steals#reference-count-details
78  * Remember to look to verify the behavior of each and every Py_ API call.
79  */
80 
81 static const char* DEFAULT_PYTHON_MODULE_PATHS[] =
82 {
83  DATADIR"/python", // install directory
84  #ifndef WIN32
85  "/usr/local/share/opencog/python",
86  "/usr/share/opencog/python",
87  #endif // !WIN32
88  NULL
89 };
90 
91 static const char* PROJECT_PYTHON_MODULE_PATHS[] =
92 {
93  PROJECT_BINARY_DIR"/opencog/cython", // bindings
94  PROJECT_SOURCE_DIR"/opencog/python", // opencog modules written in python
95  PROJECT_SOURCE_DIR"/tests/cython", // for testing
96  NULL
97 };
98 
99 // Weird hack to work-around nutty python behavior. Python sucks.
100 // I spent three effing 12 hour-days tracking this down. Cython sucks.
101 // The python bug this is working around is this: python does not
102 // know how to load modules unless there is an __init__.py in the
103 // directory. However, once it finds this, then it stops looking,
104 // and just assumes that everything is in that directory. Of course,
105 // this is a bad assumption: python modules can be in a variety of
106 // directories. In particular, they can be in the local build
107 // directories. If we put the local build directories in the search
108 // path first, then the modules are found. But if we then install this
109 // code into the system (i.e. into /usr or /usr/local) then python will
110 // still look in these build directories, even though they are bogus
111 // when the system version is installed. This, of course, results in the
112 // build directories "hiding" the install directories, causing only
113 // some, but not all of the modules to be found. This ends up being
114 // terribly confusing, because you get "ImportError: No module named
115 // blah" errors, even though you can be staring the module right in the
116 // face, and there it is!
117 //
118 // So the ugly work-around implemented here is this: If code is
119 // executing in the project source or project build directories, then
120 // add the project source and build directories to the search path, and
121 // place them first, so that they are searched before the system
122 // directories. Otherwise, do not search the build directories.
123 // This is just plain fucked up, but I cannot find a better solution.
124 static const char** get_module_paths()
125 {
126  unsigned nproj = sizeof(PROJECT_PYTHON_MODULE_PATHS) / sizeof(char**);
127  unsigned ndefp = sizeof(DEFAULT_PYTHON_MODULE_PATHS) / sizeof(char**);
128  // static const char* paths[ndefp + nproj];
129  static const char* paths[
130  (sizeof(DEFAULT_PYTHON_MODULE_PATHS) / sizeof(char**)) +
131  (sizeof(PROJECT_PYTHON_MODULE_PATHS) / sizeof(char**))];
132 
133  // Get current working directory.
134  char* cwd = getcwd(NULL, 0);
135  bool in_project = false;
136  if (0 == strncmp(PROJECT_SOURCE_DIR, cwd, strlen(PROJECT_SOURCE_DIR)) or
137  0 == strncmp(PROJECT_BINARY_DIR, cwd, strlen(PROJECT_BINARY_DIR)))
138  in_project = true;
139  free(cwd);
140 
141  // The the currrent working directory is the projet build or source
142  // directory, then search those first.
143  int ip=0;
144  if (in_project) {
145  for (unsigned i=0; i < nproj-1; i++) {
146  paths[ip] = PROJECT_PYTHON_MODULE_PATHS[i];
147  ip++;
148  }
149  }
150 
151  // Search the usual locations next.
152  for (unsigned i=0; i < ndefp-1; i++) {
153  paths[ip] = DEFAULT_PYTHON_MODULE_PATHS[i];
154  ip++;
155  }
156  paths[ip] = NULL;
157 
158  return paths;
159 }
160 
161 
173 static bool try_to_load_modules(const char ** config_paths)
174 {
175  PyObject* pySysPath = PySys_GetObject((char*)"path");
176 
177  // Add default OpenCog module directories to the Python interprator's path.
178  for (int i = 0; config_paths[i] != NULL; ++i)
179  {
180  struct stat finfo;
181  stat(config_paths[i], &finfo);
182 
183  if (S_ISDIR(finfo.st_mode))
184  {
185  PyObject* pyModulePath = PyBytes_FromString(config_paths[i]);
186  PyList_Append(pySysPath, pyModulePath);
187  Py_DECREF(pyModulePath);
188  }
189  }
190 
191  // Add custom paths for python modules from the config file.
192  if (config().has("PYTHON_EXTENSION_DIRS"))
193  {
194  std::vector<string> pythonpaths;
195  // For debugging current path
196  tokenize(config()["PYTHON_EXTENSION_DIRS"],
197  std::back_inserter(pythonpaths), ", ");
198 
199  for (std::vector<string>::const_iterator it = pythonpaths.begin();
200  it != pythonpaths.end(); ++it)
201  {
202  struct stat finfo;
203  stat(it->c_str(), &finfo);
204  if (S_ISDIR(finfo.st_mode))
205  {
206  PyObject* pyModulePath = PyBytes_FromString(it->c_str());
207  PyList_Append(pySysPath, pyModulePath);
208  Py_DECREF(pyModulePath);
209  } else {
210  logger().warn("%s: "
211  "Could not find custom python extension directory: %s ",
212  __FUNCTION__, it->c_str() );
213  }
214  }
215  }
216 
217  // NOTE: Can't use get_path_as_string() yet because it is defined in a
218  // Cython api which we can't import unless the sys.path is correct. So
219  // we'll write it out before the imports below to aid in debugging.
220  if (logger().isDebugEnabled())
221  {
222  logger().debug("Python 'sys.path' after OpenCog config adds is:");
223  Py_ssize_t pathSize = PyList_Size(pySysPath);
224  for (int i = 0; i < pathSize; i++)
225  {
226  PyObject* pySysPathLine = PyList_GetItem(pySysPath, i);
227  const char* sysPathCString = PyString_AsString(pySysPathLine);
228  logger().debug(" %2d > %s", i, sysPathCString);
229  // NOTE: PyList_GetItem returns borrowed reference so don't do this:
230  // Py_DECREF(pySysPathLine);
231  }
232  }
233 
234  // Initialize the auto-generated Cython api. Do this AFTER the python
235  // sys.path is updated so the imports can find the cython modules.
236  import_opencog__atomspace();
237 
238  // The import_opencog__atomspace() call above sets the
239  // py_atomspace() function pointer if the cython module load
240  // succeeded. But the function pointer will be NULL if the
241  // opencopg.atomspace cython module failed to load. Avert
242  // a hard-to-debug crash on null-pointer-deref, and replace
243  // it by a hard-to-debug error message.
244  if (NULL == py_atomspace) {
245  PyErr_Print();
246  logger().warn("PythonEval::%s Failed to load the "
247  "opencog.atomspace module", __FUNCTION__);
248  }
249 
250  // Now we can use get_path_as_string() to get 'sys.path'
251  // But only if import_opencog__atomspace() suceeded without error.
252  // When it fails, it fails silently, leaving get_path_as_string with
253  // a NULL PLT/GOT entry
254  if (NULL != get_path_as_string)
255  logger().info("Python 'sys.path' after OpenCog config adds is: " +
256  get_path_as_string());
257 
258  // NOTE: PySys_GetObject returns a borrowed reference so don't do this:
259  // Py_DECREF(pySysPath);
260  return (NULL != py_atomspace);
261 }
262 
264 {
265  // We don't really know the gstate yet but we'll set it here to avoid
266  // compiler warnings below.
267  PyGILState_STATE gstate = PyGILState_UNLOCKED;
268 
269  logger().debug("[global_python_initialize] Start");
270 
271  // Throw an exception if this is called more than once.
272  if (already_initialized) {
273  return;
274  throw opencog::RuntimeException(TRACE_INFO,
275  "Python initializer global_python_init() called twice.");
276  }
277 
278  // Remember this initialization.
279  already_initialized = true;
280 
281  // Start up Python.
282  if (Py_IsInitialized()) {
283  // If we were already initialized then someone else did it.
285 
286  // Just grab the GIL
287  gstate = PyGILState_Ensure();
288 
289  } else {
290  // We are doing the initialization.
292 
293  // Initialize Python (InitThreads grabs GIL implicitly)
294  Py_InitializeEx(NO_SIGNAL_HANDLERS);
295  PyEval_InitThreads();
296 
297  // Many python libraries (e.g. ROS) expect sys.argv to be set.
298  // So, avoid the error print, and let them know who we are.
299  // We must do this *before* the module pre-loading, done below.
300  static const char *argv0 = "cogserver";
301  PySys_SetArgv(1, (char **) &argv0);
302  }
303 
304  logger().debug("[global_python_initialize] Adding OpenCog sys.path "
305  "directories");
306 
307  // Get starting "sys.path".
308  PyRun_SimpleString(
309  "import sys\n"
310  "import StringIO\n"
311  );
312 
313  // Add default OpenCog module directories to the Python interprator's path.
315 
316  // Hmm. If the above returned false, we should try a different
317  // permuation of the config paths. I'm confused, though, different
318  // users are reporting conflicting symptoms. What to do?
319 
320  // Release the GIL, otherwise the Python shell hangs on startup.
322  PyGILState_Release(gstate);
323  else
324  PyEval_ReleaseLock();
325 
326  logger().debug("[global_python_initialize] Finish");
327 }
328 
330 {
331  logger().debug("[global_python_finalize] Start");
332 
333  // Cleanup Python.
335  Py_Finalize();
336 
337  // No longer initialized.
338  already_initialized = false;
339 
340  logger().debug("[global_python_finalize] Finish");
341 }
342 
344 {
345  // Check that this is the first and only PythonEval object.
346  if (singletonInstance) {
347  throw (RuntimeException(TRACE_INFO,
348  "Can't create more than one PythonEval singleton instance!"));
349  }
350 
351  // Remember our atomspace.
353  _paren_count = 0;
354 
355  // Initialize Python objects and imports.
356  //
357  // Strange but true: one can use the atomspace, and put atoms
358  // in it .. useing the type constructors and everything (e.g.
359  // the demos in the /examples/python directory) and never ever
360  // actually call global_python_initialize() ... it might never
361  // be called, if the python evaluator (i.e. this object) is
362  // never used or needed. I thought this was unexpected, so I
363  // mention it here.
366 
367  // Add the preload functions
368  if (config().has("PYTHON_PRELOAD_FUNCTIONS")) {
369  string preloadDirectory = config()["PYTHON_PRELOAD_FUNCTIONS"];
370  this->add_modules_from_path(preloadDirectory);
371  }
372 }
373 
375 {
376  logger().info("PythonEval::%s destructor", __FUNCTION__);
377 
378  // Grab the GIL
379  PyGILState_STATE gstate;
380  gstate = PyGILState_Ensure();
381 
382  // Decrement reference counts for instance Python object references.
383  Py_DECREF(_pyGlobal);
384  Py_DECREF(_pyLocal);
385 
386  // NOTE: The following come from Python C api calls that return borrowed
387  // references. However, we have called Py_INCREF( x ) to promote them
388  // to full references so we can and must decrement them here.
389  Py_DECREF(_pySysPath);
390  Py_DECREF(_pyRootModule);
391 
392  // Release the GIL. No Python API allowed beyond this point.
393  PyGILState_Release(gstate);
394 }
395 
400 {
401  if (singletonInstance) return;
402 
403  // Create the single instance of a PythonEval object.
404  singletonInstance = new PythonEval(atomspace);
405 }
406 
408 {
409  if (!singletonInstance) return;
410 
411  // Delete the singleton PythonEval instance.
412  delete singletonInstance;
413  singletonInstance = NULL;
414 }
415 
417 {
418  // Make sure we have a singleton.
419  if (!singletonInstance)
420  create_singleton_instance(atomspace);
421 
422  // Make sure the atom space is the same as the one in the singleton.
423  if (atomspace and singletonInstance->_atomspace != atomspace) {
424 
425 #define CHECK_SINGLETON
426 #ifdef CHECK_SINGLETON
427  // Someone is trying to initialize the Python interpreter on a
428  // different AtomSpace. Because of the singleton design of the
429  // the CosgServer+AtomSpace, there is no easy way to support this...
430  throw RuntimeException(TRACE_INFO,
431  "Trying to re-initialize python interpreter with different\n"
432  "AtomSpace ptr! Current ptr=%p New ptr=%p\n",
433  singletonInstance->_atomspace, atomspace);
434 #else
435  // We need to be able to call the python interpreter with
436  // different atomspaces; for example, we need to use temporary
437  // atomspaces when evaluating virtual links. So, just set it
438  // here. Hopefully the user will set it back, after using the
439  // temp atomspace. Cleary, this is not thread-safe, and will
440  // bust with multiple threads. But the whole singleton-instance
441  // design is fundamentally flawed, so there is not much we can
442  // do about it until someone takes the time to fix this class
443  // to allow multiple instances.
444  //
446 #endif
447  }
448  return *singletonInstance;
449 }
450 
452 {
453  // Grab the GIL
454  PyGILState_STATE gstate;
455  gstate = PyGILState_Ensure();
456 
457  // Get sys.path and keep the reference, used in this->add_to_sys_path()
458  // NOTE: We have to promote the reference here with Py_INCREF because
459  // PySys_GetObject returns a borrowed reference and we don't want it to
460  // go away behind the scenes.
461  _pySysPath = PySys_GetObject((char*)"path");
462  Py_INCREF(_pySysPath);
463 
464  // Get the __main__ module. NOTE: As above, PyImport_AddModule returns
465  // a borrowed reference so we must promote it with an increment.
466  _pyRootModule = PyImport_AddModule("__main__");
467  Py_INCREF(_pyRootModule);
468  PyModule_AddStringConstant(_pyRootModule, "__file__", "");
469 
470  // Add ATOMSPACE to __main__ module.
471  PyObject* pyRootDictionary = PyModule_GetDict(_pyRootModule);
472  PyObject* pyAtomSpaceObject = this->atomspace_py_object(_atomspace);
473  PyDict_SetItemString(pyRootDictionary, "ATOMSPACE", pyAtomSpaceObject);
474  Py_DECREF(pyAtomSpaceObject);
475 
476  // PyModule_GetDict returns a borrowed reference, so don't do this:
477  // Py_DECREF(pyRootDictionary);
478 
479  // These are needed for calling Python/C API functions, define
480  // them once here so we can reuse them.
481  _pyGlobal = PyDict_New();
482  _pyLocal = PyDict_New();
483 
484  // Release the GIL. No Python API allowed beyond this point.
485  PyGILState_Release(gstate);
486 
487  logger().info("PythonEval::%s Finished initialising python evaluator.",
488  __FUNCTION__);
489 }
490 
492 {
493  // The py_atomspace function pointer will be NULL if the
494  // opencopg.atomspace cython module failed to load. Avert
495  // a hard-to-debug crash on null-pointer-deref, and replace
496  // it by a hard-to-debug error message.
497  if (NULL == py_atomspace) {
498  logger().error("PythonEval::%s Failed to load the"
499  "opencog.atomspace module", __FUNCTION__);
500  return NULL;
501  }
502 
503 /***********
504  Weird ... I guess NULL atomspaces are OK!?
505  if (NULL == atomspace) {
506  logger().error("PythonEval::%s No atomspace specified!",
507  __FUNCTION__);
508  return NULL;
509  }
510 ************/
511 
512  PyObject * pyAtomSpace = py_atomspace(atomspace);
513 
514  if (!pyAtomSpace) {
515  if (PyErr_Occurred())
516  PyErr_Print();
517 
518  logger().error("PythonEval::%s Failed to get atomspace "
519  "wrapped with python object", __FUNCTION__);
520  }
521 
522  return pyAtomSpace;
523 }
524 
525 void PythonEval::print_dictionary(PyObject* obj)
526 {
527  if (!PyDict_Check(obj))
528  return;
529 
530  PyObject *pyKey, *pyKeys;
531 
532  // Get the keys from the dictionary and print them.
533  pyKeys = PyDict_Keys(obj);
534  for (int i = 0; i < PyList_Size(pyKeys); i++) {
535 
536  // Get and print one key.
537  pyKey = PyList_GetItem(pyKeys, i);
538  char* c_name = PyBytes_AsString(pyKey);
539  printf("%s\n", c_name);
540 
541  // PyList_GetItem returns a borrowed reference, so don't do this:
542  // Py_DECREF(pyKey);
543  }
544 
545  // Cleanup the Python reference count for the keys list.
546  Py_DECREF(pyKeys);
547 }
548 
554 void PythonEval::build_python_error_message( const char* function_name,
555  std::string& errorMessage)
556 {
557  PyObject *pyErrorType, *pyError, *pyTraceback, *pyErrorString;
558  std::stringstream errorStringStream;
559 
560  // Get the error from Python.
561  PyErr_Fetch(&pyErrorType, &pyError, &pyTraceback);
562 
563  // Construct the error message string.
564  errorStringStream << "Python error ";
565  if (function_name != NO_FUNCTION_NAME)
566  errorStringStream << "in " << function_name;
567  if (pyError) {
568  pyErrorString = PyObject_Str(pyError);
569  char* pythonErrorString = PyString_AsString(pyErrorString);
570  if (pythonErrorString) {
571  errorStringStream << ": " << pythonErrorString << ".";
572  } else {
573  errorStringStream << ": Undefined Error";
574  }
575 
576  // Cleanup the references. NOTE: The traceback can be NULL even
577  // when the others aren't.
578  Py_DECREF(pyErrorType);
579  Py_DECREF(pyError);
580  Py_DECREF(pyErrorString);
581  if (pyTraceback)
582  Py_DECREF(pyTraceback);
583 
584  } else {
585  errorStringStream << ": Undefined Error";
586  }
587  errorMessage = errorStringStream.str();
588 }
589 
598 void PythonEval::execute_string(const char* command)
599 {
600  PyObject *pyRootDictionary, *pyResult;
601  pyRootDictionary = PyModule_GetDict(_pyRootModule);
602  pyResult = PyRun_StringFlags(command, Py_file_input, pyRootDictionary,
603  pyRootDictionary, NO_COMPILER_FLAGS);
604  if (pyResult)
605  Py_DECREF(pyResult);
606  Py_FlushLine();
607 }
608 
609 int PythonEval::argument_count(PyObject* pyFunction)
610 {
611  PyObject* pyFunctionCode;
612  PyObject* pyArgumentCount;
613  int argumentCount;
614 
615  // Get the 'function.func_code.co_argcount' Python internal attribute.
616  pyFunctionCode = PyObject_GetAttrString(pyFunction, "func_code");
617  if (pyFunctionCode) {
618  pyArgumentCount = PyObject_GetAttrString(pyFunctionCode, "co_argcount");
619  if (pyArgumentCount) {
620  argumentCount = PyInt_AsLong(pyArgumentCount);
621  } else {
622  Py_DECREF(pyFunctionCode);
623  return MISSING_FUNC_CODE;
624  }
625  } else {
626  return MISSING_FUNC_CODE;
627  }
628 
629  // Cleanup the reference counts.
630  Py_DECREF(pyFunctionCode);
631  Py_DECREF(pyArgumentCount);
632 
633  return argumentCount;
634 }
635 
641 PyObject* PythonEval::module_for_function( const std::string& moduleFunction,
642  std::string& functionName)
643 {
644  PyObject* pyModule;
645  std::string moduleName;
646 
647  // Get the correct module and extract the function name.
648  int index = moduleFunction.find_first_of('.');
649  if (index < 0){
650  pyModule = _pyRootModule;
651  functionName = moduleFunction;
652  moduleName = "__main__";
653  } else {
654  moduleName = moduleFunction.substr(0, index);
655  pyModule = _modules[moduleName];
656  functionName = moduleFunction.substr(index+1);
657  }
658 
659  return pyModule;
660 }
661 
668 PyObject* PythonEval::call_user_function( const std::string& moduleFunction,
669  Handle arguments)
670 {
671  std::lock_guard<std::recursive_mutex> lck(_mtx);
672 
673  PyObject *pyError, *pyModule, *pyUserFunc, *pyReturnValue = NULL;
674  PyObject *pyDict;
675  std::string functionName;
676  std::string errorString;
677 
678  // Grab the GIL.
679  PyGILState_STATE gstate;
680  gstate = PyGILState_Ensure();
681 
682  // Get the module and stripped function name.
683  pyModule = this->module_for_function(moduleFunction, functionName);
684 
685  // If we can't find that module then throw an exception.
686  if (!pyModule) {
687  PyGILState_Release(gstate);
688  logger().error("Python module for '%s' not found!", moduleFunction.c_str());
689  throw (RuntimeException(TRACE_INFO, "Python module for '%s' not found!",
690  moduleFunction.c_str()));
691  }
692 
693  // Get a reference to the user function.
694  pyDict = PyModule_GetDict(pyModule);
695  pyUserFunc = PyDict_GetItemString(pyDict, functionName.c_str());
696 
697  // PyModule_GetDict returns a borrowed reference, so don't do this:
698  // Py_DECREF(pyDict);
699 
700  // If we can't find that function then throw an exception.
701  if (!pyUserFunc) {
702  PyGILState_Release(gstate);
703  logger().error("Python function '%s' not found!", moduleFunction.c_str());
704  throw (RuntimeException(TRACE_INFO, "Python function '%s' not found!",
705  moduleFunction.c_str()));
706  }
707 
708  // Promote the borrowed reference for pyUserFunc since it will
709  // be passed to a Python C API function later that "steals" it.
710  Py_INCREF(pyUserFunc);
711 
712  // Make sure the function is callable.
713  if (!PyCallable_Check(pyUserFunc)) {
714  Py_DECREF(pyUserFunc);
715  PyGILState_Release(gstate);
716  logger().error("Python user function '%s' not callable!",
717  moduleFunction.c_str());
718  throw (RuntimeException(TRACE_INFO,
719  "Python function '%s' not callable!", moduleFunction.c_str()));
720  }
721 
722  // Get the expected argument count.
723  int expectedArgumentCount = this->argument_count(pyUserFunc);
724  if (expectedArgumentCount == MISSING_FUNC_CODE) {
725  PyGILState_Release(gstate);
726  throw (RuntimeException(TRACE_INFO,
727  "Python function '%s' error missing 'func_code'!",
728  moduleFunction.c_str()));
729  }
730 
731  // Get the actual argument count, passed in the ListLink.
732  if (arguments->getType() != LIST_LINK) {
733  PyGILState_Release(gstate);
734  throw RuntimeException(TRACE_INFO,
735  "Expecting arguments to be a ListLink!");
736  }
737  LinkPtr linkArguments(LinkCast(arguments));
738  int actualArgumentCount = linkArguments->getArity();
739 
740  // Now make sure the expected count matches the actual argument count.
741  if (expectedArgumentCount != actualArgumentCount) {
742  PyGILState_Release(gstate);
743  throw (RuntimeException(TRACE_INFO,
744  "Python function '%s' which expects '%d arguments,"
745  " called with %d arguments!", moduleFunction.c_str(),
746  expectedArgumentCount, actualArgumentCount
747  ));
748  }
749 
750  // Create the Python tuple for the function call with python
751  // atoms for each of the atoms in the link arguments.
752  PyObject* pyArguments = PyTuple_New(actualArgumentCount);
753  PyObject* pyAtomSpace = this->atomspace_py_object(_atomspace);
754  const HandleSeq& argumentHandles = linkArguments->getOutgoingSet();
755  int tupleItem = 0;
756  for (HandleSeq::const_iterator it = argumentHandles.begin();
757  it != argumentHandles.end(); ++it) {
758 
759  // Place a Python atom object for this handle into the tuple.
760  PyObject* pyAtom = py_atom(it->value(), pyAtomSpace);
761  PyTuple_SetItem(pyArguments, tupleItem, pyAtom);
762 
763  // PyTuple_SetItem steals it's item so don't do this:
764  // Py_DECREF(pyAtom)
765 
766  ++tupleItem;
767  }
768  Py_DECREF(pyAtomSpace);
769 
770  // Execute the user function and store its return value.
771  pyReturnValue = PyObject_CallObject(pyUserFunc, pyArguments);
772 
773  // Cleanup the reference counts for Python objects we no longer reference.
774  // Since we promoted the borrowed pyExecuteUserFunc reference, we need
775  // to decrement it here. Do this before error checking below since we'll
776  // need to decrement these references even if there is an error.
777  Py_DECREF(pyUserFunc);
778  Py_DECREF(pyArguments);
779 
780  // Check for errors.
781  pyError = PyErr_Occurred();
782  if (pyError) {
783 
784  // Construct the error message and throw an exception.
785  this->build_python_error_message(moduleFunction.c_str(), errorString);
786  PyGILState_Release(gstate);
787  throw RuntimeException(TRACE_INFO, errorString.c_str());
788 
789  // PyErr_Occurred returns a borrowed reference, so don't do this:
790  // Py_DECREF(pyError);
791  }
792 
793  // Release the GIL. No Python API allowed beyond this point.
794  PyGILState_Release(gstate);
795 
796  return pyReturnValue;
797 }
798 
799 Handle PythonEval::apply(AtomSpace* as, const std::string& func, Handle varargs)
800 {
801  std::lock_guard<std::recursive_mutex> lck(_mtx);
802  RAII raii(this, as);
803 
804  UUID uuid = 0;
805 
806  // Get the atom object returned by this user function.
807  PyObject* pyReturnAtom = this->call_user_function(func, varargs);
808 
809  // If we got a non-null atom were no errors.
810  if (pyReturnAtom) {
811 
812  // Grab the GIL.
813  PyGILState_STATE gstate;
814  gstate = PyGILState_Ensure();
815 
816  // Get the handle UUID from the atom.
817  PyObject* pyAtomUUID = PyObject_CallMethod(pyReturnAtom, (char*) "handle_uuid",
818  NULL);
819 
820  // Make sure we got an atom UUID.
821  PyObject* pyError = PyErr_Occurred();
822  if (pyError || !pyAtomUUID) {
823  PyGILState_Release(gstate);
824  throw RuntimeException(TRACE_INFO,
825  "Python function '%s' did not return Atom!", func.c_str());
826  }
827 
828  // Get the UUID from the python UUID.
829  uuid = static_cast<unsigned long>(PyLong_AsLong(pyAtomUUID));
830 
831  // Cleanup the reference counts.
832  Py_DECREF(pyReturnAtom);
833  Py_DECREF(pyAtomUUID);
834 
835  // Release the GIL. No Python API allowed beyond this point.
836  PyGILState_Release(gstate);
837 
838  } else {
839 
840  throw RuntimeException(TRACE_INFO,
841  "Python function '%s' did not return Atom!", func.c_str());
842  }
843 
844  return Handle(uuid);
845 }
846 
851 TruthValuePtr PythonEval::apply_tv(AtomSpace *as, const std::string& func, Handle varargs)
852 {
853  std::lock_guard<std::recursive_mutex> lck(_mtx);
854  RAII raii(this, as);
855 
856  // Get the python truth value object returned by this user function.
857  PyObject *pyTruthValue = call_user_function(func, varargs);
858 
859  // If we got a non-null truth value there were no errors.
860  if (NULL == pyTruthValue) {
861  throw RuntimeException(TRACE_INFO,
862  "Python function '%s' did not return TruthValue!",
863  func.c_str());
864  }
865 
866  // Grab the GIL.
867  PyGILState_STATE gstate = PyGILState_Ensure();
868 
869  // Get the truth value pointer from the object (will be encoded
870  // as a long by PyVoidPtr_asLong)
871  PyObject *pyTruthValuePtrPtr = PyObject_CallMethod(pyTruthValue,
872  (char*) "truth_value_ptr_object", NULL);
873 
874  // Make sure we got a truth value pointer.
875  PyObject *pyError = PyErr_Occurred();
876  if (pyError or !pyTruthValuePtrPtr) {
877  PyGILState_Release(gstate);
878  throw RuntimeException(TRACE_INFO,
879  "Python function '%s' did not return TruthValue!",
880  func.c_str());
881  }
882 
883  // Get the pointer to the truth value pointer. Yes, it does
884  // contain a pointer to the shared_ptr not the underlying.
885  TruthValuePtr* tvpPtr = static_cast<TruthValuePtr*>
886  (PyLong_AsVoidPtr(pyTruthValuePtrPtr));
887 
888  // Assign the truth value pointer using this pointer before
889  // we decrement the reference to pyTruthValue since that
890  // will delete this pointer.
891  TruthValuePtr tvp = *tvpPtr;
892 
893  // Cleanup the reference counts.
894  Py_DECREF(pyTruthValuePtrPtr);
895  Py_DECREF(pyTruthValue);
896 
897  // Release the GIL. No Python API allowed beyond this point.
898  PyGILState_Release(gstate);
899  return tvp;
900 }
901 
902 std::string PythonEval::apply_script(const std::string& script)
903 {
904  std::lock_guard<std::recursive_mutex> lck(_mtx);
905 
906  PyObject* pyError = NULL;
907  PyObject *pyCatcher = NULL;
908  PyObject *pyOutput = NULL;
909  std::string result;
910  bool errorRunningScript;
911  std::string errorString;
912 
913  // Grab the GIL
914  PyGILState_STATE gstate;
915  gstate = PyGILState_Ensure();
916 
917  PyRun_SimpleString("_opencog_output_stream = StringIO.StringIO()\n"
918  "_python_output_stream = sys.stdout\n"
919  "sys.stdout = _opencog_output_stream\n"
920  "sys.stderr = _opencog_output_stream\n");
921 
922  // Execute the script. NOTE: This call replaces PyRun_SimpleString
923  // which was masking errors because it calls PyErr_Clear() so the
924  // call to PyErr_Occurred below was returning false even when there
925  // was an error.
926  this->execute_string(script.c_str());
927 
928  // Check for errors in the script.
929  pyError = PyErr_Occurred();
930 
931  // If the script executed without error...
932  if (!pyError) {
933  // Get the output stream as a string so we can return it.
934  errorRunningScript = false;
935  pyCatcher = PyObject_GetAttrString(_pyRootModule,
936  "_opencog_output_stream");
937  pyOutput = PyObject_CallMethod(pyCatcher, (char*)"getvalue", NULL);
938  result = PyBytes_AsString(pyOutput);
939 
940  // Cleanup reference counts for Python objects we no longer reference.
941  Py_DECREF(pyCatcher);
942  Py_DECREF(pyOutput);
943 
944  } else {
945  // Remember the error and get the error string for the throw below.
946  errorRunningScript = true;
947  this->build_python_error_message(NO_FUNCTION_NAME, errorString);
948 
949  // PyErr_Occurred returns a borrowed reference, so don't do this:
950  // Py_DECREF(pyError);
951  }
952 
953  // Close the output stream.
954  PyRun_SimpleString("sys.stdout = _python_output_stream\n"
955  "sys.stderr = _python_output_stream\n"
956  "_opencog_output_stream.close()\n");
957 
958  // Release the GIL. No Python API allowed beyond this point.
959  PyGILState_Release(gstate);
960 
961  // If there was an error throw an exception so the user knows the
962  // script had a problem.
963  if (errorRunningScript) {
964  logger().warn() << errorString;
965  errorString += "\n";
966  throw (RuntimeException(TRACE_INFO, errorString.c_str()));
967  }
968 
969  // printf("Python says that: %s\n", result.c_str());
970  return result;
971 }
972 
973 void PythonEval::add_to_sys_path(std::string path)
974 {
975  PyObject* pyPathString = PyBytes_FromString(path.c_str());
976  PyList_Append(_pySysPath, pyPathString);
977 
978  // We must decrement because, unlike PyList_SetItem, PyList_Append does
979  // not "steal" the reference we pass to it. So this:
980  //
981  // PyList_Append(this->pySysPath, PyBytes_FromString(path.c_str()));
982  //
983  // leaks memory. So we need to save the reference as above and
984  // decrement it, as below.
985  //
986  Py_DECREF(pyPathString);
987 }
988 
989 
990 const int ABSOLUTE_IMPORTS_ONLY = 0;
991 
992 void PythonEval::import_module( const boost::filesystem::path &file,
993  PyObject* pyFromList)
994 {
995  // The pyFromList parameter corresponds to what would appear in an
996  // import statement after the import:
997  //
998  // from <module> import <from list>
999  //
1000  // When this list is empty, this corresponds to an import of the
1001  // entire module as is done in the simple import statement:
1002  //
1003  // import <module>
1004  //
1005  string fileName, moduleName;
1006 
1007  // Get the module name from the Python file name by removing the ".py"
1008  fileName = file.filename().c_str();
1009  moduleName = fileName.substr(0, fileName.length()-3);
1010 
1011  logger().info(" importing Python module: " + moduleName);
1012 
1013  // Import the entire module into the current Python environment.
1014  PyObject* pyModule = PyImport_ImportModuleLevel((char*) moduleName.c_str(),
1015  _pyGlobal, _pyLocal, pyFromList,
1017 
1018  // If the import succeeded...
1019  if (pyModule) {
1020  PyObject* pyModuleDictionary = PyModule_GetDict(pyModule);
1021 
1022  // Add the ATOMSPACE object to this module
1023  PyObject* pyAtomSpaceObject = this->atomspace_py_object(_atomspace);
1024  PyDict_SetItemString(pyModuleDictionary,"ATOMSPACE",
1025  pyAtomSpaceObject);
1026 
1027  // This decrement is needed because PyDict_SetItemString does
1028  // not "steal" the reference, unlike PyList_SetItem.
1029  Py_DECREF(pyAtomSpaceObject);
1030 
1031  // We need to increment the pyModule reference because
1032  // PyModule_AddObject "steals" it and we're keeping a copy
1033  // in our modules list.
1034  Py_INCREF(pyModule);
1035 
1036  // Add the module name to the root module.
1037  PyModule_AddObject(_pyRootModule, moduleName.c_str(), pyModule);
1038 
1039  // Add the module to our modules list. So don't decrement the
1040  // Python reference in this function.
1041  _modules[moduleName] = pyModule;
1042 
1043  // otherwise, handle the error.
1044  } else {
1045  if(PyErr_Occurred())
1046  PyErr_Print();
1047  logger().warn() << "Couldn't import '" << moduleName << "' module";
1048  }
1049 
1050 }
1051 
1056 void PythonEval::add_module_directory(const boost::filesystem::path &directory)
1057 {
1058  vector<boost::filesystem::path> files;
1059  vector<boost::filesystem::path> pyFiles;
1060 
1061  // Loop over the files in the directory looking for Python files.
1062  copy(boost::filesystem::directory_iterator(directory),
1063  boost::filesystem::directory_iterator(), back_inserter(files));
1064  for(vector<boost::filesystem::path>::const_iterator it(files.begin());
1065  it != files.end(); ++it) {
1066  if(it->extension() == boost::filesystem::path(".py"))
1067  pyFiles.push_back(*it);
1068  }
1069 
1070  // Add the directory we are adding to Python's sys.path
1071  this->add_to_sys_path(directory.c_str());
1072 
1073  // The pyFromList variable corresponds to what would appear in an
1074  // import statement after the import:
1075  //
1076  // from <module> import <from list>
1077  //
1078  // When this list is empty, as below, this corresponds to an import of the
1079  // entire module as is done in the simple import statement:
1080  //
1081  // import <module>
1082  //
1083  PyObject* pyFromList = PyList_New(0);
1084 
1085  // Import each of the ".py" files as a Python module.
1086  for(vector<boost::filesystem::path>::const_iterator it(pyFiles.begin());
1087  it != pyFiles.end(); ++it)
1088  this->import_module(*it, pyFromList);
1089 
1090  // Cleanup the reference count for the from list.
1091  Py_DECREF(pyFromList);
1092 }
1093 
1098 void PythonEval::add_module_file(const boost::filesystem::path &file)
1099 {
1100  // Add this file's parent path to sys.path so Python imports
1101  // can find it.
1102  this->add_to_sys_path(file.parent_path().c_str());
1103 
1104  // The pyFromList variable corresponds to what would appear in an
1105  // import statement after the import:
1106  //
1107  // from <module> import <from list>
1108  //
1109  // When this list is empty, as below, this corresponds to an import of the
1110  // entire module as is done in the simple import statement:
1111  //
1112  // import <module>
1113  //
1114 
1115  // Import this file as a module.
1116  PyObject* pyFromList = PyList_New(0);
1117  this->import_module(file, pyFromList);
1118  Py_DECREF(pyFromList);
1119 }
1120 
1125 void PythonEval::add_modules_from_path(std::string pathString)
1126 {
1127  if ('/' == pathString[0]) {
1128  add_modules_from_abspath(pathString);
1129  return;
1130  }
1131 
1132  bool did_load = false;
1133  const char** config_paths = get_module_paths();
1134  for (int i = 0; config_paths[i] != NULL; ++i) {
1135  std::string abspath = config_paths[i];
1136  abspath += "/";
1137  abspath += pathString;
1138 
1139  // If the resulting path is a directory or a regular file,
1140  // then load it.
1141  struct stat finfo;
1142  stat(abspath.c_str(), &finfo);
1143  if (S_ISDIR(finfo.st_mode) or S_ISREG(finfo.st_mode)) {
1144  add_modules_from_abspath(abspath);
1145  did_load = true;
1146  }
1147  }
1148 
1149  if (not did_load) {
1150  Logger::Level btl = logger().getBackTraceLevel();
1151  logger().setBackTraceLevel(Logger::Level::NONE);
1152  logger().error() << "Failed to load python module \'" << pathString
1153  << "\', searched directories:";
1154  for (int i = 0; config_paths[i] != NULL; ++i) {
1155  logger().error() << "Directory: " << config_paths[i];
1156  }
1157  logger().setBackTraceLevel(btl);
1158  }
1159 }
1160 
1161 void PythonEval::add_modules_from_abspath(std::string pathString)
1162 {
1163  logger().info("Adding Python module (or directory): " + pathString);
1164 
1165  // Grab the GIL
1166  PyGILState_STATE gstate;
1167  gstate = PyGILState_Ensure();
1168 
1169  struct stat finfo;
1170  stat(pathString.c_str(), &finfo);
1171 
1172  if (S_ISDIR(finfo.st_mode))
1173  add_module_directory(pathString);
1174  else if (S_ISREG(finfo.st_mode))
1175  add_module_file(pathString);
1176  else
1177  logger().error() << "Python module path \'" << pathString
1178  << "\' can't be found";
1179 
1180  // Release the GIL. No Python API allowed beyond this point.
1181  PyGILState_Release(gstate);
1182 }
1183 
1184 // The python interpreter chokes if we send it lines, instead of
1185 // blocks. Thus, we have to save up whole blocks. A block consists
1186 // of:
1187 // 1) Something that starts unindented, and continues until the
1188 // start of the next non-comment unindented line, or until
1189 // end-of-file.
1190 // 2) Anything surrounded by parenthesis, regardless of indentation.
1191 //
1192 void PythonEval::eval_expr(const std::string& partial_expr)
1193 {
1194  // Trim whitespace, and comments before doing anything,
1195  // Otherwise, the various checks below fail.
1196  std::string part = partial_expr.substr(0,
1197  partial_expr.find_last_not_of(" \t\n\r") + 1);
1198 
1199  size_t cmnt = part.find('#');
1200  if (std::string::npos != cmnt)
1201  part = part.substr(0, cmnt);
1202 
1203  // If we get a newline by itself, just ignore it.
1204  // Ignore leading comments; don't ignore empty line.
1205  int c = 0;
1206  size_t part_size = part.size();
1207  if (0 == part_size and 0 < partial_expr.size()) goto wait_for_more;
1208 
1209  if (0 < part_size) c = part[0];
1210 
1211  logger().debug("[PythonEval] get line:\n%s\n", partial_expr.c_str());
1212 
1213  // Check if there are open parentheses. If so, then we must
1214  // assume there will be more input that closes them off.
1215  {
1216  size_t open = std::count(part.begin(), part.end(), '(');
1217  size_t clos = std::count(part.begin(), part.end(), ')');
1218  _paren_count += open - clos;
1219  if (0 < _paren_count) goto wait_for_more;
1220  }
1221 
1222  // If the line starts with whitespace (tab or space) then assume
1223  // that it is standard indentation, and wait for the first
1224  // unindented line (or end-of-file).
1225  if (' ' == c or '\t' == c) goto wait_for_more;
1226 
1227  // If the line ends with a colon, its not a complete expression,
1228  // and we must wait for more input, i.e. more input is pending.
1229  if (0 < part_size and part.find_last_of(":\\") + 1 == part_size)
1230  goto wait_for_more;
1231 
1232  _input_line += part;
1233  _input_line += '\n'; // we stripped this off, above
1234  logger().info("[PythonEval] eval_expr:\n%s", _input_line.c_str());
1235 
1236  // This is the cogserver shell-freindly evaluator. We must
1237  // stop all exceptions thrown in other layers, or else we
1238  // will crash the cogserver. Pass the exception message to
1239  // the user, who can read and contemplate it: it is almost
1240  // surely a syntax error in the python code.
1241  _result = "";
1242  try
1243  {
1244  _result = this->apply_script(_input_line);
1245  }
1246  catch (const RuntimeException &e)
1247  {
1248  _result = e.getMessage();
1249  _result += "\n";
1250  }
1251  _input_line = "";
1252  _paren_count = 0;
1253  _pending_input = false;
1254  return;
1255 
1256 wait_for_more:
1257  _result = "";
1258  _pending_input = true;
1259  // Add this expression to our evaluation buffer.
1260  _input_line += part;
1261  _input_line += '\n'; // we stripped this off, above
1262 }
1263 
1265 {
1266  std::string r = _result;
1267  _result.clear();
1268  return r;
1269 }
static bool already_initialized
Definition: PythonEval.cc:60
PyObject * _pySysPath
Definition: PythonEval.h:139
const int ABSOLUTE_IMPORTS_ONLY
Definition: PythonEval.cc:990
static const char ** get_module_paths()
Definition: PythonEval.cc:124
int argument_count(PyObject *pyFunction)
Definition: PythonEval.cc:609
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
const int MISSING_FUNC_CODE
Definition: PythonEval.cc:55
virtual std::string poll_result()
Definition: PythonEval.cc:1264
void add_modules_from_abspath(std::string path)
Definition: PythonEval.cc:1161
std::shared_ptr< TruthValue > TruthValuePtr
Definition: TruthValue.h:85
PythonEval(AtomSpace *)
Definition: PythonEval.cc:343
std::string apply_script(const std::string &script)
Definition: PythonEval.cc:902
void build_python_error_message(const char *function_name, std::string &errorMessage)
Definition: PythonEval.cc:554
PyObject * module_for_function(const std::string &moduleFunction, std::string &functionName)
Definition: PythonEval.cc:641
AtomSpace * _atomspace
Definition: PythonEval.h:110
void add_modules_from_path(std::string path)
Definition: PythonEval.cc:1125
Type getType() const
Definition: Atom.h:197
#define NO_COMPILER_FLAGS
Definition: PythonEval.cc:58
std::shared_ptr< Link > LinkPtr
Definition: Atom.h:53
void print_dictionary(PyObject *)
Definition: PythonEval.cc:525
PyObject * _pyRootModule
Definition: PythonEval.h:137
void global_python_finalize()
Definition: PythonEval.cc:329
void add_module_file(const boost::filesystem::path &file)
Definition: PythonEval.cc:1098
static PythonEval & instance(AtomSpace *atomspace=NULL)
Definition: PythonEval.cc:416
static void delete_singleton_instance()
Definition: PythonEval.cc:407
void initialize_python_objects_and_imports(void)
Definition: PythonEval.cc:451
void add_to_sys_path(std::string path)
Definition: PythonEval.cc:973
static bool try_to_load_modules(const char **config_paths)
Definition: PythonEval.cc:173
unsigned long UUID
UUID == Universally Unique Identifier.
Definition: Handle.h:46
void import_module(const boost::filesystem::path &file, PyObject *pyFromList)
Definition: PythonEval.cc:992
PyObject * _pyLocal
Definition: PythonEval.h:136
Handle apply(AtomSpace *, const std::string &func, Handle varargs)
Definition: PythonEval.cc:799
const int SIMPLE_STRING_SUCCESS
Definition: PythonEval.cc:53
static const char * DEFAULT_PYTHON_MODULE_PATHS[]
Definition: PythonEval.cc:81
std::map< std::string, PyObject * > _modules
Definition: PythonEval.h:141
const char * NO_FUNCTION_NAME
Definition: PythonEval.cc:52
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
static void create_singleton_instance(AtomSpace *)
Definition: PythonEval.cc:399
std::string _input_line
Definition: GenericEval.h:42
PyObject * atomspace_py_object(AtomSpace *)
Definition: PythonEval.cc:491
void add_module_directory(const boost::filesystem::path &directory)
Definition: PythonEval.cc:1056
static const char * PROJECT_PYTHON_MODULE_PATHS[]
Definition: PythonEval.cc:91
virtual void eval_expr(const std::string &)
Definition: PythonEval.cc:1192
const int SIMPLE_STRING_FAILURE
Definition: PythonEval.cc:54
PyObject * _pyGlobal
Definition: PythonEval.h:135
void global_python_initialize()
Definition: PythonEval.cc:263
TruthValuePtr apply_tv(AtomSpace *, const std::string &func, Handle varargs)
Definition: PythonEval.cc:851
static bool initialized_outside_opencog
Definition: PythonEval.cc:61
static PythonEval * singletonInstance
Definition: PythonEval.h:108
static std::recursive_mutex _mtx
Definition: PythonEval.h:133
std::string _result
Definition: PythonEval.h:143
PyObject * call_user_function(const std::string &func, Handle varargs)
Definition: PythonEval.cc:668
void execute_string(const char *command)
Definition: PythonEval.cc:598
const int NO_SIGNAL_HANDLERS
Definition: PythonEval.cc:51