Skip to main content
gamedev.net
🔒 Locked

Embedded Python: Distribution Error

Started by telaryus 7 replies 2.7k views
Original Post
telaryus
telaryus
Hello, I've made a simple program to test embedding Python before putting it into a C/C++ application that I am currently working on. The program is pretty straight forward and is as follows:
#include <Python.h>

int main(int, char *argv[])
{
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  PyRun_SimpleString("import time\n"
                     "print time.ctime(time.time())");
  Py_Finalize();

  return 0;
}
All it does is print out the date and time something like: Fri Feb 27 16:47:45 2009 I am using Python 2.6 and VS2005 to compile and link. I have the additional includes set to c:\python26\include the additional library directories set to c:\python26\libs the additional dependencies set to python26.lib Running Warning Lv4 (/W4) with warnings as errors (/WX) That's the setup. The issue that I'm running into at the moment is that on my machine this executable runs cleanly without reporting any sort of error. However, when I move it to another machine. Taking the python26.dll along with it to run Side-by-Side. When the application is run I get the message on the command line that " 'import site' failed ". I'm not really sure what is happening and since the computer that I'm testing on doesn't have Python installed I can't run the script in verbose mode to get a trace back on the what is going on (and doing so on my computer doesn't report any errors.) Now although the error message is produced the application still runs correctly. But the fact that the error happens annoys me and I was wondering if anybody else has this issue or has had it and knows how to fix it or if no one has had this issue what are you doing that might be different from what I'm doing? Thanks for your help. Regards. ~Neb
"My word is my bond and here I stand."
SiCrane
SiCrane
Most Python modules are not actually part of the Python binary, they're implemented in Python scripts. Basically, you'll need to bundle any of the Python scripts that you use along with your program. In this case, "'import site' failed" means that the site.py file that you'll find in Python26\Lib directory needs to be packaged with your program. Generally I put those kinds of dependencies in a zip file and add that zip file to my Python search path in the application.
telaryus
telaryus
OK. I understand what you mean, but I apparently don't understand how to implement it.

I've updated my code to the following:
#include <Python.h>#include <string>  using std::string;int main(int, char *argv[]){  Py_SetProgramName(argv[0]);  Py_Initialize();  string path(Py_GetPath());  path += ";.\\includes.zip";  PySys_SetPath( const_cast<char*>(path.c_str()) );  PyRun_SimpleString("import site\n"                     "import time\n"                     "import sys\n"                     "print time.ctime(time.time())\n"                     "print sys.path");  Py_Finalize();  return 0;}


And I've placed site.py into a zip and put it Side-by-Side(SxS) with the .exe for now.

I was still getting the " 'import site' failed " message. So, I pulled site.py out of the .zip and just placed it SxS with the executable.

Still get the " 'import site' failed " message, however the site.pyc was created. -.-'

The path that is being printed is:
['C:\\Documents and Settings\\Neb\\Desktop\\python26.zip', '.\\DLLs', '.\\lib', '.\\lib\\plat-win', '.\\lib\\lib-tk', 'C:\\Documents and Settings\\Neb\\Desktop', '.\\includes.zip']

So it appears that the path is correct, but apparently not. =/

Any further help in resolving this would be much appreciated.

Regards.
~Neb

**EDIT**
I added "import site\n" to the string being run to track down possible dependencies to that .py file and added them to the .zip.

The output now looks like:
'import site' failed; use -v for traceback
Fri Feb 27 18:00:48 2009
['C:\\Documents and Settings\\Neb\\Desktop\\python26.zip', 'C:\\Documents and Settings\\Neb\\Desktop\\DLLs', 'C:\\Documents and Settings\\Neb\\Desktop\\lib', 'C:\\Documents and Settings\\Neb\\Desktop\\lib\\plat-win', 'C:\\Documents and Settings\\Neb\\Desktop\\lib\\lib-tk', 'C:\\Documents and Settings\\Neb\\Desktop', 'C:\\Documents and Settings\\Neb\\Desktop\\includes.zip']

I had to end up adding the following to the includes.zip to be able to "import site" and still have it fail.

encodings/
_abcoll.py
abc.py
codecs.py
copy_reg.py
functools.py
genericpath.py
linecache.py
locale.py
ntpath.py
os.py
re.py
site.py
sre_compile.py
sre_constants.py
sre_parse.py
stat.py
types.py
UserDict.py
warnings.py

[Edited by - telaryus on February 27, 2009 8:35:04 PM]
"My word is my bond and here I stand."
SiCrane
SiCrane
I'm not entirely sure what's going on now. Two things I suggest trying: 1) use PyErr_Print() to see if you can get more detailed error message. 2) Go to your Python26\Lib directory on your development computer and delete all the .pyc files, then run your application. The files that your program uses should all generate new .pyc files so you don't need to guess which ones you need.
telaryus
telaryus
OK so added the following after my script runs.
  if (PyErr_Occurred() != NULL)    PyErr_Print();


Cleared out all my .pyc files and regenerated the same 19 files listed before so left my .zip alone.

Same output as before with no additional information printed.

Regards.
~Neb
"My word is my bond and here I stand."
SiCrane
SiCrane
Ok, one last stab in the dark: in my embedded Python applications, I put the zip at the beginning of sys.path rather than at the end. That seems to be the only other difference between what I do and what you're doing. If that doesn't help, I'm tapped out of ideas.
telaryus
telaryus
Same output as before ><;

I think Python doesn't like me. =/
I'm gonna try on some different computers to see if it really does work, but my test machine is just being stupid.

However, if anyone else might have some ideas. I'd love to hear them.

Thanks.
~Neb
"My word is my bond and here I stand."
telaryus
telaryus
All Right!

Found the issue.
It's not the PyRun_SimpleString() script that is throwing the import site failed, it's the Py_Initialize(). ><;

So now the question is, how do I set up paths before initializing python?

Regards.
~Neb
"My word is my bond and here I stand."
telaryus
telaryus
All right~!

So thanks to the help of SiCrane, I was able to figure out that Py_Initialize() was the source of the " 'import site' failed " error message.

And after doing a little bit of research and some crafty google searches I was able to find some information that helped to resolve the issue.

I came across this bug report. Which then lead me to this code.

Quick version is basically that there is a global flag in the pythonrun.c file called Py_NoSiteFlag. This flag is used to during Py_Initialize() to initialize the site.

So by setting this flag to a non-zero value running my code on other machines now runs completely clean with no errors because it no longer is trying to initialize site.

My code now looks like this:
#include <Python.h>#include <string>  using std::string;int main(int, char *argv[]){  Py_SetProgramName(argv[0]);  Py_NoSiteFlag = 1;  Py_InitializeEx(0);    string path(".\\includes.zip;");  path += Py_GetPath();  PySys_SetPath(const_cast<char*>(path.c_str()) );  PyRun_SimpleString("import time\n"                     "print time.ctime(time.time())\n");  if (PyErr_Occurred() != NULL)    PyErr_Print();  Py_Finalize();  return 0;}


*Sigh of relief* That's one error to scratch off my list.

Thanks again SiCrane for your help~

Regards.
~Neb
"My word is my bond and here I stand."

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.