DaPhil
DaPhil

Reputation: 1589

Getting Python to work in Cocoa App

I am currently trying to get Python to work within a Cocoa App. My first step is to include Python so that Xcode can link against it. Since OS X Mavericks, the Python.framework is no longer in the SDK, so I followed this instructions to get it to work. Creating a project and following the steps described, Xcode gives me an error message:

CpResource libpython2.7.dylib /Users/Phil/Library/Developer/Xcode/DerivedData/Python_Scripting-hiipjmacxsirqkfqczdjdaxbqgfj/Build/Products/Debug/Python\ Scripting.app/Contents/Resources/libpython2.7.dylib

cd "/Users/Phil/Documents/Xcode/Python Scripting"

builtin-copy -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git -exclude .hg -resolve-src-symlinks /Users/Phil/Documents/Xcode/Python\ Scripting/libpython2.7.dylib /Users/Phil/Library/Developer/Xcode/DerivedData/Python_Scripting-hiipjmacxsirqkfqczdjdaxbqgfj/Build/Products/Debug/Python\ Scripting.app/Contents/Resources

error: /Users/Phil/Documents/Xcode/Python Scripting/../../../Python: No such file or directory

I am pretty sure that I followed the instructions correctly (e.g. Py_IsInitialized() is recognized). But: What does the statement Confirm the dialog box, and now Xcode is set to link against libpython2.7.dylib (by using the same -L and -l option settings as above). mean? Do I have to set up some linker flags manually?

Upvotes: 2

Views: 1339

Answers (1)

Zorg
Zorg

Reputation: 1018

When you drag the system libpython2.7.dylib to your project, make sure the "Copy Items..." checkbox is unchecked. You want the library to just be referenced, not copied into your project.

The CpResource command you pasted though convinces me that Xcode is trying to copy the file from your project (which doesn't exist) into your .app's Resources. You don't want that either. If the dylib file is in your target's Build Phases under Copy Bundle Resources, then you should remove it. (You can search for CpResource and you'll find people having similar issues).

It is worth mentioning that Apple recommends not relying on the system installed version when embedding a scripting language, and to instead bundle your own version. This way you're not at mercy of Apple's dated version, or if their version is later changed or removed from the system.

Edit:

If you want to bundle your own Python version, this is what I did for one of my apps (I used version 3.3):

  • Download and compile Python from its source code. I recommend compiling it statically (it might be set to do this by default).
  • Copy the static library (.a file), python3.3 library folder, and include files that were spit out into my Xcode project.
  • Confirm that there is a build phase for my target to copy the python3.3 library folder from my project into my .app
  • Set environment variables PYTHONHOME and PYTHONPATH to my python3.3 directory located inside my .app (path retrieved using NSBundle) before initializing Python at run-time
  • #include "Python.h" and make a call to Py_Initialize()
  • Append the path of the python3.3/lib-dynload/ directory (inside my .app) to Python's sys.path variable, so that the C compiled modules in there are importable

And it should work.

Optional:

You may not want to include > 100 MB of Python data in your app. I used this command to convert all the standard library .py source files into .pyc bytecode files in-place:

path/to/built/python -m compileall path/to/python3.3/ -b

(-b may not be needed/relevant in 2.x)

Then I proceeded onto removing __pycache__, and any packages/modules I know I didn't need (e.g. tkinter, antigravity, etc.). I brought the size of my bundled python files to around 20 MB (7 MB when zipped)

Upvotes: 4

Related Questions