Bundle python tool in Cocoa app with easy_install
-
28-10-2019 - |
Question
My Cocoa app requires a Python command line tool to be installed on the user's system using easy_install. Ideally, I'd want to bundle one bash file with my app which I can then run. But as far as I know this is not possible, because packages are installed in the "site-packages" directory of Python.
Is there a way to create a "package" of those files? If not, how should I run the easy_install installation? I wanted to bundle a .pkg file with my app which I can then open if necessary, but I wasn't able to let this installation package run a script only.
If you have ideas on how to fix this, I'd be glad.
Kind regards, Fabian
Solution
If you can ship the command line tool with your application, and if only your application will be using it (instead of the tool being used directly by the user), you can directly include and use the command line tool with your application like so:
- Store the command line tool somewhere in your application directory.
- Set the Python module search path so that it looks for the module you need.
Setting the Python module search path relative to a Python program can be done with
import sys
import os.path as path
sys.path.append(path.join(path.dirname(__file__),
'<relative path between this program and the command line tool module>'))
import <command line tool module>
The relative path can be written with the ..
parent directory convention: this works both on Unix (including Mac OS X) and Windows.
PS: If many programs need to access the command line tool module, you can:
Either put the above code in each of your programs,
or, if you want something easier to maintain, you can create your own module
my_runner
and use it as a proxy: your modulemy_runner
would import all the originalrunner
functions like so:import sys import os.path as path sys.path.append(path.join(path.dirname(__file__), '<relative path between this program and the original ino module>')) from ino.runner import *
You can then use the original runner module in all your programs through your proxy, by simply doing "normal" imports of your own
my_runner
module:from my_runner import main
PPS: If you want a more robust path that works even if the working directory later changes, it is possible to convert a potentially local path to an absolute path with: path.join(path.abspath(path.dirname(__file__)),…
.
OTHER TIPS
Thanks to EOL I got it working now. The solution involved several steps listed below.
Remove dependencies by packaging the
.egg
files and referencing them like this:import sys import os.path as path sys.path.append(path.join(path.dirname(__file__), '<relative path to .egg file>')) from dependency import something
Build a single
.egg
file from the now independent python module usingsetup.py
- Reference the resulting
.egg
file in the command line tool like in1.
- Bundle the single
.egg
file and the command line tool in the Cocoa app
I hope this will be useful to someone.