1

If this question could be worded better/needs to be split into many questions, please alert me

I need to package Python scripts in order to ship them as single-executables (ideally), or single-executables with supporting files (non-ideally).

I have seen py2app and py2exe. They do not fit my requirements, as I am looking for a single method to do this, and in the future may need to have the packaged scripts interact with the executable that they are being run from.

What is the best way to go about this? The scripts which I would be embedding may even require multiple files, which complicates matters I'm sure.

If I wanted to use an interpreter other than CPython (ie: PyPy or Stackless) in the future, would the process be different (other than API calls in the C++ executable)?

Does Python have to be installed on the computers which would be running the package, or does embedding Python mean that it is fully embedded? I saw on the Python Wiki something about Py_SetPythonHome(), which would indicate to me that it needs Python (or at least its libraries) to be installed. Am I correct?

PyroAVR
  • 719
  • 1
  • 8
  • 19
  • There is several ways to embed Python. This should be a good first read to do it "the hard way" (which you will probably need to, if you want a deep interaction): https://docs.python.org/2/extending/embedding.html – Diane M Jan 04 '16 at 00:24
  • That's where I started my research. I started with that and am pleased with it, but am not sure how to go about keeping my scripts and their dependencies inside a single executable. – PyroAVR Jan 04 '16 at 01:14

3 Answers3

2

PyInstaller with the --onefile option will put everything inside a single file, though it will take a little more time to startup. I'm afraid it's not compatible with PyPy, but it should not be so tricky to get it working using Stackless.

Good luck!

cdonts
  • 9,304
  • 4
  • 46
  • 72
0

Are you sure that you need to embed the Python files?

I ask because you mention you want to package the Python files as single executables. Couldn't you install Python on the target machine and since Python scripts are executables on their own, you would only need something to kick them off. A master python script could kick off all the rest of the scripts.

Otherwise you should look in C++ what can run a Python script. Then have the master python script run all the other scripts.

William Ross
  • 3,568
  • 7
  • 42
  • 73
  • I need to embed the scripts because I would like the program to be as easy to uninstall as it is to install. I would like to avoid installing Python on the target computer so that when the user no longer wishes to use my program, they can drag it to the trash and it will be gone without a trace. – PyroAVR Jan 04 '16 at 01:13
  • You can have an installer program both install and uninstall python so have the installer do: 1) install python 2) run scripts 3) uninstall python. Of course you have to know how to use an installer program like Install Anywhere, or similar. – William Ross Jan 04 '16 at 02:06
0

Yes you can!

The easiest is with newest Python3 <OS> <arch> embeddable zip file, which contains .so/.dll and all modules.

Instructions are here: https://docs.python.org/3/extending/embedding.html

#include <Python.h>

int
main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    Py_Initialize();
    PyRun_SimpleString("from time import time,ctime\n"
                       "print('Today is', ctime(time()))\n");
    Py_Finalize();
    PyMem_RawFree(program);
    return 0;
}

The trickier part is communication between your C++ code and Python code.

If you only have to pass a few strings back and forth, that's trivial, but if you want a very tight integration, then you'll probably need a few of these:

  • create a Python module in (C++ code, C ABI) and inject it -- that means Python will be able to run import yourmod; yourmod.yourfunc(...) which will run your C++ custom code and/or
  • resolve and call Python functions from C++ (the inverse) https://stackoverflow.com/a/3310608/705086

Single executable

If you cannot have an installer, and really do not wish to have a bunch of .DLL/.so/etc it's described e.g. here Merge DLL into EXE? and it's ABI-specific, there will be one way for Windows, another Linux, etc, and you may have to override Python's import machinery (so that it doesn't look for dll/so in the file system) -- at this point, you may as well use PyInstaller or extend/merge PyInstaller with your application. Please research https://github.com/pyinstaller/pyinstaller/tree/develop/bootloader/src and evaluate how hard that might be

PyPy

Simple embedding is possisble http://doc.pypy.org/en/latest/embedding.html but single-file embedding is not. You could hack PyPy source and build custom embeddable object, but you'd be the first to do so :)

Stackless

Should be as simple as regular CPythion

Community
  • 1
  • 1
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120