7

I'm trying to embed python, and provide the dll and a zip of the python libraries and not use any installed python. That is, if a user doesn't have python, I want my code to work using the provided dll/zip.

This post seems to describe the process, except it isn't working for me.

If I run the following, my code will run as long as I have Python27.dll and a folder named Python27 that contains the DLL and Lib folders.

Py_SetProgramName(argv[0]);  /* optional but recommended */
Py_SetPythonHome("Python27");
Py_Initialize();

If I remove the Python27 folder, the code fails - so I am pulling in the local copy, not any installed python.

However, if I zip the local Python27 folder, the code stops running, giving "ImportError: No module named site".

PEP273 makes it sound like this should just work, but everything I've tried has failed.

Can anyone shed light on how to get embedded python to run from a zip file?

Given that there are related questions that have gone unanswered, I think it would be helpful if people would add a comment if they have successfully gotten reading from a zip file working, even if they aren't sure what I might need to fix.

That would at least help me understand if I should keep looking for an answer!

Update: No matter what I try (even with LoadLibrary as suggested), I can run my program from a fully unzipped directory. Any time I remove the directory with DLLs/* and Lib/* and put in Python27.zip instead, I just get

ImportError: No module named site
Community
  • 1
  • 1
Brett Stottlemyer
  • 2,734
  • 4
  • 26
  • 38

4 Answers4

7

I had two issues.

The not well documented 'Py_NoSiteFlag' fixed the

ImportError: No module named site

first problem. Next, I had to update paths. In the end, I ended up with the following for initialization:

Py_NoSiteFlag=1;
Py_SetProgramName(argv[0]);
Py_SetPythonHome(".");
Py_InitializeEx(0);
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path = ['.','python27.zip','python27.zip/DLLs','python27.zip/Lib','python27.zip/site-packages']");

[edit to address question in comments] Once you have the zip'd file loading, you still need to pass files to the python engine. Here's what I use (argument and file existence checks not included).

PyObject* PyFileObject = PyFile_FromString(argv[1], "r");
int res = PyRun_SimpleFile(PyFile_AsFile(PyFileObject), argv[1]);

[/edit]

Brett Stottlemyer
  • 2,734
  • 4
  • 26
  • 38
  • Is this the solution ? If not, can you please edit your initial post? – Paco Sep 05 '13 at 17:24
  • This worked for me. I was holding off in case someone contributed something new, since I don't get the bounty for answering my own question. Marked as the answer now that the bounty expired. – Brett Stottlemyer Sep 05 '13 at 19:39
  • This solution works partially for me - If I use python27.zip and the Py_NoSiteFlag, I can load Python in memory but I am unable to import my custom package. Note that everything works fine when using the Python folders not zipped. Could it be related to the site.py not being imported? – MasterMind Feb 21 '14 at 13:29
  • @BrettStottlemyer I'm having the exact same problem as you, can you tell where did you put your .py files? For example if you made a file name mine.py and you used it while embedding. Where would u put it? – João Pereira Jun 21 '14 at 18:17
2

I believe your original problem is that you placed the folders in your python zip, when you should place the contents of the DLLs and Lib folders into the python zip.

Instead of this:

python27.zip
  DLLs
    *.*
  Lib
    *.*

You should have:

python27.zip
  *.* from DLLs
  *.* from Lib
KymikoLoco
  • 1,433
  • 1
  • 15
  • 17
0

Note that windows searches for libraries in the executable's path first and only then starts looking in other places. If your python27.dll is always placed in the executable's path and you use LoadLibrary("python27.dll") or bind to the library directly, you just always use the local python version. If the \python27-folder is empty then, your interpreter fails. If the dll is not there, you use the global interpreter.

Move the dll into a separate folder so windows will only load it if asked for it by LoadLibrary("\p27\python27.dll")

user2722968
  • 13,636
  • 2
  • 46
  • 67
  • The problem isn't that it is picking up the wrong python. The problem is that it isn't loading anything from the zip file. This is when using the local version. – Brett Stottlemyer Aug 29 '13 at 19:57
0

Well, I'd like to post another link here in case someone else encounter similar issue. I have to say that due to bad luck, I happened to download the python 3.3.4, which has a bug when using zipped library, see http://bugs.python.org/issue20852